From 4e7be6670e5406371015541476e1b7899bb7245a Mon Sep 17 00:00:00 2001 From: boinred Date: Mon, 28 Sep 2026 05:49:58 +0000 Subject: [PATCH 1/3] ci: prefix build and dashboard job names with their workflow Both workflows named their matrix jobs just "${{ matrix.os }}", so the build and dashboard checks were indistinguishable ("macos-latest", "windows-latest") when selecting required status checks for the main branch ruleset. Jobs now report as "build ()" and "dashboard ()". Claude-Session: https://claude.ai/code/session_01BQy9NxDcMgXNygFbZQbBnS --- .github/workflows/build.yml | 3 ++- .github/workflows/dashboard.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c423b96..95a2924 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,8 @@ permissions: jobs: build-test: - name: ${{ matrix.os }} + # 목적: branch ruleset 필수 체크에서 build/dashboard job을 구분할 수 있도록 워크플로 접두어 부여 + name: build (${{ matrix.os }}) strategy: fail-fast: false matrix: diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml index d0fe587..abe0391 100644 --- a/.github/workflows/dashboard.yml +++ b/.github/workflows/dashboard.yml @@ -40,7 +40,8 @@ permissions: jobs: build-test: - name: ${{ matrix.os }} + # 목적: branch ruleset 필수 체크에서 build/dashboard job을 구분할 수 있도록 워크플로 접두어 부여 + name: dashboard (${{ matrix.os }}) strategy: fail-fast: false matrix: From bee7c196c166ca090a163bf932e9feb213b77921 Mon Sep 17 00:00:00 2001 From: boinred Date: Mon, 5 Oct 2026 06:09:00 +0000 Subject: [PATCH 2/3] docs: add CLAUDE.md and docs/CODEMAP.md, drop PDCA rules - CLAUDE.md imports AGENTS.md and docs/CODEMAP.md so Claude Code and Codex share one rule set, plus Claude-specific git/PR and golden-hash notes. - docs/CODEMAP.md: project graph, directory map, engine types, session data flow, app/template wiring, test tools, CI jobs and known pitfalls, so agents can locate code without re-reading the tree. - AGENTS.md: remove the PDCA automation rule (no longer used), add a code map rule, retitle as shared Codex / Claude Code instructions. - Remove remaining PDCA mentions from README trees and the Maui README (its docs/archive link pointed at a deleted folder). Claude-Session: https://claude.ai/code/session_01BQy9NxDcMgXNygFbZQbBnS --- AGENTS.md | 11 +-- CLAUDE.md | 19 ++++ FastPortDashboard.Maui/README.md | 4 +- README.ko.md | 2 +- README.md | 2 +- docs/CODEMAP.md | 163 +++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 CLAUDE.md create mode 100644 docs/CODEMAP.md diff --git a/AGENTS.md b/AGENTS.md index d307d8d..fc7ce07 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# Global Codex Instructions +# Agent Instructions (Codex / Claude Code 공통) ## Language @@ -12,13 +12,10 @@ - Apply the skill with emphasis on explicit assumptions, simplicity first, surgical changes, verifiable success criteria, and verification. - If the skill is not available in the current session, read `/Users/boinred/.codex/skills/karpathy-guidelines/SKILL.md` and follow those instructions as the fallback. -## PDCA Automation Rule +## Code Map Rule -- `$pdca do {feature}`로 개발을 진행한 경우, 구현 완료 후 가능한 한 자동으로 `$pdca analyze {feature}`를 실행하여 design/code gap을 확인한다. -- 분석 결과 iterate가 필요한 경우, 사용자 추가 지시를 기다리지 말고 가능한 범위에서 `$pdca iterate {feature}` 흐름까지 자동 진행한다. -- iterate 이후에는 다시 analyze를 수행하고, match rate가 완료 기준에 도달하거나 더 이상 안전하게 자동 수정할 수 없을 때까지 반복한다. -- 완료 기준에 도달한 경우, 가능한 한 `$pdca report {feature}`까지 자동으로 작성하여 PDCA 흐름을 마무리한다. -- 자동 진행 중 테스트 실패, 설계 충돌, 위험한 변경, 사용자 결정이 필요한 범위가 발견되면 즉시 중단하고 현재 상태와 필요한 결정을 보고한다. +- 코드 탐색 전에 `docs/CODEMAP.md`를 먼저 읽고, 작업에 필요한 파일만 열어 토큰을 절약한다. +- 프로젝트·디렉터리 추가/삭제, 공개 타입 이동, 빌드·테스트 명령 변경처럼 코드맵 내용이 달라지는 변경을 하면 같은 커밋에서 `docs/CODEMAP.md`도 갱신한다. ## Commenting Rule diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e64f2e0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,19 @@ +# CLAUDE.md + +공통 에이전트 규칙(언어, 코딩, 주석 규칙)은 `AGENTS.md`에 있고, 저장소 구조는 `docs/CODEMAP.md`에 있다. +Claude Code는 아래 import로 두 파일을 자동으로 읽는다. 규칙은 `AGENTS.md` 한 곳에서만 수정한다. + +@AGENTS.md +@docs/CODEMAP.md + +## Claude Code 전용 메모 + +### Git / PR +- 커밋 author·committer: `boinred `. `Co-Authored-By: Claude` 트레일러는 넣지 않는다. +- `main`은 브랜치 보호(ruleset) 대상: 직접 push 금지, PR + 필수 체크 `build (ubuntu-latest)`, `build (macos-latest)`, `build (windows-latest)` 통과 후 merge commit으로 머지. +- 릴리스 브랜치 이름은 `builds/release` (점 `.`이 아니라 슬래시 `/`). 승격은 `main` → `builds/release` PR. + +### 변경 시 함께 해야 하는 일 +- `LibCommons/**`, `LibNetworks/**`, `template-projects/FastPortGameServerTemplate/**`, `template-projects/Protos/**` 수정 → scaffold golden hash 갱신 필수: + `tests/scaffold/run.sh --update-golden case-01-simple` 후 `tests/scaffold/run.sh` 전체 통과 확인. +- `.github/workflows/*.yml`의 job `name` 변경 → main ruleset 필수 체크 이름도 함께 바꿔야 PR이 머지됨. diff --git a/FastPortDashboard.Maui/README.md b/FastPortDashboard.Maui/README.md index 05d3b7e..68c61c9 100644 --- a/FastPortDashboard.Maui/README.md +++ b/FastPortDashboard.Maui/README.md @@ -6,9 +6,7 @@ produced by `ServerTelemetryExportBackgroundService` and visualises throughput + session KPIs in 1-second intervals. > **Foundation cycle scope** — single view, single chart (server throughput), -> 6 KPIs. See `docs/archive/2026-05/maui-telemetry-dashboard-foundation/` for -> the full PDCA record. Multi-run / RTT charts / report export will come in -> follow-up cycles. +> 6 KPIs. Multi-run / RTT charts / report export will come in follow-up cycles. ## Prerequisites diff --git a/README.ko.md b/README.ko.md index e3512eb..5e5e761 100644 --- a/README.ko.md +++ b/README.ko.md @@ -402,7 +402,7 @@ FastPortSharp/ ├── 📂 FastPortDashboard.Maui/ # MAUI desktop dashboard (macOS / Windows) │ # FastPortSharp.Dashboard.sln 로 빌드 │ -├── 📂 docs/ # 성능 리포트, PDCA archive +├── 📂 docs/ # 벤치마크 리포트, runbook, CODEMAP.md └── FastPortSharp.sln ``` diff --git a/README.md b/README.md index d14bbbc..d23a88c 100644 --- a/README.md +++ b/README.md @@ -411,7 +411,7 @@ FastPortSharp/ ├── 📂 FastPortDashboard.Maui/ # MAUI desktop dashboard (macOS / Windows) │ # Built via FastPortSharp.Dashboard.sln │ -├── 📂 docs/ # Performance reports, PDCA archive +├── 📂 docs/ # Benchmark reports, runbooks, CODEMAP.md └── FastPortSharp.sln ``` diff --git a/docs/CODEMAP.md b/docs/CODEMAP.md new file mode 100644 index 0000000..2534c46 --- /dev/null +++ b/docs/CODEMAP.md @@ -0,0 +1,163 @@ +# FastPortSharp Code Map + +> LLM/에이전트용 저장소 지도. 코드를 열기 전에 이 문서로 위치를 찾고, 필요한 파일만 읽는다. +> 구조가 바뀌면 같은 커밋에서 이 문서도 갱신한다 (`AGENTS.md` Code Map Rule). +> 최종 갱신: 2026-10-05 (`main` 1aa6e63 + job 이름 변경 기준) + +## 1. 한눈에 보기 + +- .NET 10 / C# 14. `SocketAsyncEventArgs` 기반 TCP 엔진(`LibCommons` + `LibNetworks`) + 게임 서버 템플릿 + 부하/검증 도구 + MAUI 대시보드. +- 솔루션 2개 + - `FastPortSharp.sln`: 엔진, 샘플 서버/클라이언트, 템플릿, 테스트 도구 (Linux/macOS/Windows 빌드 가능) + - `FastPortSharp.Dashboard.sln`: `FastPortDashboard.Core` / `.Maui` / `FastPortDashboardTests` / `LibTestTelemetry` (MAUI workload 필요, macOS·Windows만) +- 와이어 포맷: `[UInt16 LE 전체 길이(헤더 포함)][int32 LE packetId][protobuf payload]`. 패킷 최대 65,535B. + +## 2. 프로젝트 의존 그래프 + +``` +LibCommons ◀── LibNetworks ◀──┬── FastPortServer + ▲ ▲ ├── FastPortClient ──────────────▶ Protocols + │ │ ├── template-projects/FastPortGameServerTemplate (+ .SampleClient) + │ │ ├── FastPortDashboard.Core ──▶ LibTestTelemetry + │ │ └── tests-projects/FastPortTestSmokeServer ──▶ LibTestTelemetry, Protocols + │ │ + └── tests-projects/FastPortTestLoadRunner (LibNetworks 미사용, 자체 소켓) ──▶ LibTestTelemetry, Protocols +tests-projects/FastPortTestLoadValidation ──▶ LibTestTelemetry (LoadRunner를 프로세스로 실행) +tests-projects/FastPortTests (MSTest) ──▶ LibCommons, LibNetworks, LoadRunner, LoadValidation, SmokeServer, LibTestTelemetry +tests-projects/FastPortDashboardTests (MSTest) ──▶ FastPortDashboard.Core +FastPortDashboard.Maui ──▶ FastPortDashboard.Core +``` + +템플릿은 `LibCommons` + `LibNetworks`만 참조한다 (`Protocols`/`FastPortServer`/테스트 프로젝트 참조 금지 — scaffold가 엔진만 복사). + +## 3. 디렉터리 맵 + +| 경로 | 역할 | +|---|---| +| `LibCommons/` | 버퍼, `BasePacket`, ID 생성, 지연 통계, 타이머 큐 | +| `LibNetworks/` | Listener / Connector / Session 엔진 | +| `Protocols/Protos/` | 엔진 샘플용 proto (`commons.proto`: `ProtocolId`, `ResultCode`, `Header` / `tests.proto`: Ping·Echo·Error) | +| `FastPortServer/` | 엔진 샘플 서버 (Generic Host, Windows Service 지원) | +| `FastPortClient/` | 엔진 샘플 클라이언트 (`LatencyStats` 사용) | +| `template-projects/FastPortGameServerTemplate/` | 게임 서버 스타터 (Serilog, DI, dispatcher/handler) | +| `template-projects/FastPortGameServerTemplate.SampleClient/` | 템플릿 echo round-trip 검증 클라이언트 | +| `template-projects/Protos/` | 템플릿 공유 proto (`PacketIds.proto` enum, `Sample.proto` Echo 메시지). 각 소비 프로젝트가 ``로 자체 생성 | +| `FastPortDashboard.Core/` | 대시보드 로직 (JSONL 폴링, 차트 수학, Echo 클라이언트, ViewModel) | +| `FastPortDashboard.Maui/` | MAUI UI (macOS Catalyst / Windows) | +| `tests-projects/FastPortTests/` | 엔진·도구 단위/통합 테스트 (MSTest) | +| `tests-projects/FastPortDashboardTests/` | 대시보드 Core 테스트 (MSTest) | +| `tests-projects/FastPortTestSmokeServer/` | 계측 포함 echo 서버 (텔레메트리 JSONL export, idle 정리) | +| `tests-projects/FastPortTestLoadRunner/` | 10K 세션 부하 생성기 (CLI) | +| `tests-projects/FastPortTestLoadValidation/` | 단계별 부하 검증 하네스 (LoadRunner 실행 + 서버 메트릭 병합·판정) | +| `tests-projects/LibTestTelemetry/` | 서버 텔레메트리 수집/스냅샷/JSONL 계약 | +| `scripts/scaffold-game-server.{sh,ps1}` | 템플릿 → 새 게임 서버 솔루션 생성 | +| `scripts/cloud/`, `scripts/load-validation/` | 클라우드(Azure/OCI) 부하 검증 보조 스크립트 | +| `tests/scaffold/` | scaffold golden 테스트 (`run.sh` / `run.ps1`, case-01~08) | +| `docs/` | 벤치마크 리포트, 부하 검증 runbook/가이드, 이 코드맵 | +| `.github/workflows/` | `build.yml`, `dashboard.yml`, `scaffold.yml` | + +## 4. 엔진 핵심 + +### LibCommons + +| 파일 | 타입 | 요점 | +|---|---|---| +| `IBuffers.cs` | `IBuffers` | `Write`, `Peek(ref byte[])`, `Drain`, `TryGetBasePackets`, `CanReadSize` | +| `ArrayPoolCircularBuffers.cs` | `ArrayPoolCircularBuffers` | **실사용 기본 구현**. `ArrayPool` 대여, 부족 시 확장(상한 없음 → 상한은 `BaseSession`이 강제), `Lock` 보호 | +| `BaseCircularBuffers.cs` / `BaseQueueBuffers.cs` | 레거시 구현 | 테스트·비교용 | +| `BasePacket.cs` | `BasePacket` | `HeaderSize = 2`, payload 복사본 보유, `Data`(ReadOnlySpan) | +| `IDGenerator.cs` | `IDGenerator` | 세션 ID 발급 | +| `LatencyStats.cs` | `LatencyStats` 외 | RTT/서버 처리/네트워크 지연 통계 (FastPortClient) | +| `Timers/` | `ITimerQueue`, `TimerQueue`, `IMonotonicTimeSource` | 단조 시계 기반 타이머 큐 (SmokeServer `SessionIdleTracker`가 사용) | + +### LibNetworks + +| 파일 | 타입 | 요점 | +|---|---|---| +| `BaseSocket.cs` | `BaseSocket` | listener/connector 공통 소켓 보유 | +| `BaseListener.cs` | `BaseListener` (abstract) | `StartAccept(ip, port[, backlog, outstandingAccepts])`, `RequestShutdown()`. accept → `IClientSessionFactory.Create` → `OnAccepted` (세션 생성은 accept pump 밖으로 offload). 관측 hook: `OnAcceptSucceeded/SessionCreated/SessionTaskStarted/AcceptFailed/ListenerSocketError` | +| `BaseMessageListener.cs` | `BaseMessageListener` | `BaseListener` + maxConnections 1000 (서버들이 상속) | +| `BaseConnector.cs` / `BaseMessageConnector.cs` | `BaseConnector` | `StartConnect(ip, port, connectionCount)` → `IServerSessionFactory.Create` | +| `Sessions/BaseSession.cs` | `BaseSession` (abstract, ~1.3K줄) | 세션 엔진 본체. 아래 5절 참고 | +| `Sessions/BaseSessionClient.cs` | `BaseSessionClient` | **서버 측에서 accept된 클라이언트 세션**. `Id`, `OnAccepted()` | +| `Sessions/BaseSessionServer.cs` | `BaseSessionServer` | **클라이언트 측에서 서버에 연결된 세션**. `OnConnected()` | +| `Sessions/IServerSessionFactory.cs` | `IClientSessionFactory` ⚠️ | 파일명과 타입명이 서로 뒤바뀜 (아래 9절) | +| `Sessions/IClientSessionFactory.cs` | `IServerSessionFactory` ⚠️ | 〃 | +| `Sessions/SessionSendOptions.cs` | `SessionSendOptions` | 송신 큐 상한(기본 1MB), chunk 64KB, drain 예산 | +| `Sessions/NetworkDisconnectReason.cs` | enum | `RemoteClosed`…`LocalShutdown`, `InvalidPacketHeader`, `ReceiveBufferOverflow`, `PacketHandlerError` | +| `Sessions/SendCompletionTracker.cs` | internal | 송신 완료 바이트 추적. 현재 엔진은 미사용, `FastPortTests`만 참조 (`InternalsVisibleTo`) | +| `Extensions/BasePacket+Extensions.cs` | `ParseMessageFromPacket` | payload 선두 int32 packetId + protobuf 파싱 | +| `AddressConverter.cs` | `AddressConverter` | ip/port → `EndPoint` 변환 | +| `Extensions/Socket+Extensions.cs` | `SetKeepAlive` | TCP keep-alive 설정 확장 | +| `SocketEventsPool.cs` | internal | SAEA 풀. 현재 어디에서도 사용하지 않음 | + +## 5. 데이터 흐름 (BaseSession) + +``` +[수신] SAEA ReceiveAsync (세션당 8KB 고정 배열, 동기 완료는 루프 처리) + → ProcessReceiveCompleted: 미파싱 바이트 > MaxReceiveBufferedBytes(기본 1MB, virtual) 이면 disconnect(ReceiveBufferOverflow) + → m_ReceivedBuffers.Write → SemaphoreSlim signal + → Task DoWorkReceivedBuffers: TryGetBasePackets + 실패 시 header size < 2 → disconnect(InvalidPacketHeader), 아니면 partial로 대기 + → bounded Channel(1000) → Task DoWorkReceivedPackets → OnReceived(packet) + handler 예외 → disconnect(PacketHandlerError) + +[송신] TryRequestSendMessage(packetId, IMessage) / TryRequestSendBuffers(span) + → 큐 바이트 예약(SessionSendOptions.MaxQueuedBytes 초과 시 거부) → ArrayPool 대여 + 헤더 기록 + → unbounded Channel → Task DoWorkSendBuffers: 최대 16 segment batch, drain 예산 후 Yield, transient 오류 backoff + +[종료] RequestDisconnect(reason): 1회만 실행 → OnNetworkSessionDisconnected(reason) → CTS cancel → socket close → 채널 complete → OnDisconnected +``` + +- 세션당 백그라운드 Task 3개 (`DoWorkReceivedBuffers`, `DoWorkReceivedPackets`, `DoWorkSendBuffers`). `WaitSession()`으로 종료 대기. +- 관측 hook (`protected virtual OnNetwork*`): SocketError, PacketReceived, ReceiveCompleted, OperationDuration, BytesSent, SendRequested/Completed/Abandoned/Backpressure/Rejected/DrainYield/BufferSample, SessionDisconnected(reason). 엔진은 텔레메트리 구현을 모름 → SmokeServer 세션이 override해 `IServerTelemetry`로 연결. + +## 6. 앱·템플릿 + +| 프로젝트 | 진입점 / 구성 | 핵심 타입 | +|---|---|---| +| FastPortServer | `Program.cs` (Generic Host), `appsettings.json`: `Logging`, `LatencyStats` | `FastPortServer : BaseMessageListener`, `FastPortClientSession : BaseSessionClient`, `FastPortClientSessionManager`(빈 stub) | +| FastPortClient | `Program.cs`, `appsettings.json`: `Logging`, `LatencyStats` | `FastPortConnector : BaseConnector`, `FastPortServerSession : BaseSessionServer` | +| GameServerTemplate | `Program.cs` DI: `IGameServerTelemetry`→`NullGameServerTelemetry`, `IPacketHandler`→`EchoHandler`, `PacketDispatcher`, `IClientSessionFactory`→`GameSessionFactory`, `GameServer`, `GameServerHostedService`. `appsettings.json`: `Serilog`, `GameServer` | `GameServer : BaseMessageListener`, `GameSession : BaseSessionClient` (`Send`), `PacketDispatcher` (packetId → handler, 예외 catch), `GameSessionFactory` (`BufferCapacityBytes` 8KB) | +| Template.SampleClient | `appsettings.json`: `Serilog`, `SampleClient` | `SampleClientConnector : BaseMessageConnector`, `SampleClientSession : BaseSessionServer`, `SampleClientHostedService` (1001 전송 → 1002 대기) | +| SmokeServer | `appsettings.json`: `FastPortTestSmokeServer`, `SessionIdleCleanup` | `FastPortTestSmokeServer : BaseMessageListener`, `FastPortTestSmokeClientSession` (hook → 텔레메트리), `SessionIdleTracker`, `ServerTelemetryExportBackgroundService` (JSONL) | +| Dashboard.Core | — | `JsonlPollingAdapter`(SmokeServer JSONL 읽기), `LineChartMath`, `EchoClient*`(LibNetworks 연결), `DashboardViewModel`, `EchoClientViewModel` (CommunityToolkit.Mvvm) | + +**템플릿에 패킷 추가**: `template-projects/Protos/`에 메시지 추가 → `PacketIds.proto` enum에 ID 추가(사용자 정의 ≥ 2000, C#에서는 `PACKET_IDS_` 접두어 제거됨) → `IPacketHandler` 구현(`PacketId => (int)PacketIds.X`) → `Program.cs`에 `AddSingleton()`. + +## 7. 테스트·검증 도구 + +| 대상 | 위치 | 비고 | +|---|---|---| +| 엔진/도구 테스트 | `tests-projects/FastPortTests/*Tests.cs` | 파일명이 대상 타입을 따름 (예: `BaseSessionReceivePolicyTests`, `BaseSessionSendPolicyTests`, `ArrayPoolCircularBufferTest`, `TimerQueueTests`, `BaseListenerShutdownTests`). 소켓 테스트는 loopback `SocketPair` 헬퍼 사용 | +| 대시보드 테스트 | `tests-projects/FastPortDashboardTests/` | Adapters, Charts, EchoClient, ViewModels, E2E(Mock) | +| 부하 생성 | `FastPortTestLoadRunner` | 주요 옵션: `--host --port --sessions --payload --duration --ramp-up --rate --pacing-policy --output` | +| 부하 검증 | `FastPortTestLoadValidation` | `--profile --stage --server-metrics --runner-project --dry-run` 등. 서버 JSONL과 러너 결과 병합·임계값 판정 | +| scaffold | `tests/scaffold/run.sh` / `run.ps1` | case-01 sha256/tree golden. 실패 시 scaffold stdout/stderr 마지막 60줄 출력 | + +## 8. 빌드·테스트·CI + +```bash +dotnet build FastPortSharp.sln -c Release +dotnet test FastPortSharp.sln -c Release # FastPortTests +dotnet test tests-projects/FastPortDashboardTests -c Release # Dashboard Core 테스트 (MAUI 불필요) +tests/scaffold/run.sh [--script ps1] [--update-golden case-01-simple] [case...] +``` + +| 워크플로 | 트리거 | job 이름 | +|---|---|---| +| `build.yml` | `main`, `builds/release` push/PR | `build (ubuntu-latest / macos-latest / windows-latest)` — main 필수 체크 | +| `dashboard.yml` | 위 브랜치 + Dashboard·엔진 경로 변경 시 | `dashboard (macos-latest / windows-latest)` | +| `scaffold.yml` | `main` push / 모든 PR + scaffold·템플릿·엔진·Protos 경로 변경 시 | ` / `, `cross-OS byte-identical compare` (windows/ps1 ≈ 16분) | + +## 9. 주의사항 (자주 밟는 함정) + +- **scaffold golden**: scaffold가 복사하는 `LibCommons/`, `LibNetworks/`, `template-projects/FastPortGameServerTemplate/`, `template-projects/Protos/` 파일 내용이 golden sha256에 포함됨 → 수정 시 `tests/scaffold/run.sh --update-golden case-01-simple` 필수 (주석만 바꿔도 해당). +- **팩토리 파일명 뒤바뀜**: `IClientSessionFactory.cs`에 `IServerSessionFactory`가, `IServerSessionFactory.cs`에 `IClientSessionFactory`가 선언됨. 타입 검색은 파일명이 아니라 타입명으로. +- **Client/Server 명명**: `BaseSessionClient` = 서버가 accept한 세션, `BaseSessionServer` = 클라이언트가 연결한 세션. +- **미사용 코드**: `BaseSession` 생성자의 `sendbuffers`(IBuffers), `BaseListener.C_MaxConnections`(저장만 함), `SocketEventsPool`, `FastPortClientSessionManager`(빈 stub). +- **Dashboard.sln**에는 `LibCommons`/`LibNetworks`가 포함되지 않아 Release 빌드에서도 ProjectReference가 Debug 구성으로 빌드됨. +- **MAUI CI**: `--no-restore` Release 빌드 전 restore에도 `-p:Configuration=Release` 필요 (NETSDK1047/1112). +- **macOS symlink**: `/var` → `/private/var`. 절대 경로 sln 빌드 시 ProjectReference 중복 restore 경합 → scaffold smoke build는 dest로 이동 후 상대 경로로 빌드. +- **릴리스 브랜치 이름**: `builds/release` (`builds.release` 아님). +- **코드 주석의 `Design Ref: §...`**: 과거 설계 문서 참조이며 해당 문서는 저장소에 없음. From e082d8ff1e7b8ac93a0664fe0d1857e1810d17ce Mon Sep 17 00:00:00 2001 From: boinred Date: Mon, 5 Oct 2026 06:12:28 +0000 Subject: [PATCH 3/3] ci(dashboard): pin MAUI workload set to 10.0.401 `dotnet workload install maui` picked up the new workload set 10.0.401.1, which moves MacCatalyst to SDK 27.0.10722. That SDK requires Xcode 27.0, but the macos-latest runner ships Xcode 26.6, so dashboard (macos-latest) failed with "requires Xcode 27.0" even on a docs-only change. Pin the set that last passed (10.0.401: MacCatalyst 26.5.10318, MAUI 10.0.20, matching the project's Microsoft.Maui.Controls 10.0.20). Claude-Session: https://claude.ai/code/session_01BQy9NxDcMgXNygFbZQbBnS --- .github/workflows/dashboard.yml | 5 ++++- docs/CODEMAP.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml index abe0391..150e9e6 100644 --- a/.github/workflows/dashboard.yml +++ b/.github/workflows/dashboard.yml @@ -73,9 +73,12 @@ jobs: shell: bash run: dotnet --info + # 목적: workload set 버전 고정. 미지정 시 최신 set(예: 10.0.401.1 → MacCatalyst SDK 27.0)이 + # 설치되어 runner의 Xcode(26.x)와 맞지 않아 빌드 실패. 10.0.401 = MacCatalyst 26.5 + MAUI 10.0.20 + # (FastPortDashboard.Maui의 Microsoft.Maui.Controls 10.0.20과 일치). 올릴 때는 runner Xcode 버전과 함께 확인. - name: Install MAUI workload shell: bash - run: dotnet workload install maui + run: dotnet workload install maui --version 10.0.401 # 목적: MAUI는 Release에서만 maccatalyst RuntimeIdentifiers(x64/arm64)를 추가하므로, # --no-restore Release build와 같은 Configuration으로 restore해야 NETSDK1047 방지 diff --git a/docs/CODEMAP.md b/docs/CODEMAP.md index 2534c46..9320d91 100644 --- a/docs/CODEMAP.md +++ b/docs/CODEMAP.md @@ -157,7 +157,7 @@ tests/scaffold/run.sh [--script ps1] [--update-golden case-01-simple] [case...] - **Client/Server 명명**: `BaseSessionClient` = 서버가 accept한 세션, `BaseSessionServer` = 클라이언트가 연결한 세션. - **미사용 코드**: `BaseSession` 생성자의 `sendbuffers`(IBuffers), `BaseListener.C_MaxConnections`(저장만 함), `SocketEventsPool`, `FastPortClientSessionManager`(빈 stub). - **Dashboard.sln**에는 `LibCommons`/`LibNetworks`가 포함되지 않아 Release 빌드에서도 ProjectReference가 Debug 구성으로 빌드됨. -- **MAUI CI**: `--no-restore` Release 빌드 전 restore에도 `-p:Configuration=Release` 필요 (NETSDK1047/1112). +- **MAUI CI**: `--no-restore` Release 빌드 전 restore에도 `-p:Configuration=Release` 필요 (NETSDK1047/1112). workload는 `dotnet workload install maui --version 10.0.401`로 고정 — 최신 set은 runner Xcode보다 높은 MacCatalyst SDK를 요구할 수 있음. - **macOS symlink**: `/var` → `/private/var`. 절대 경로 sln 빌드 시 ProjectReference 중복 restore 경합 → scaffold smoke build는 dest로 이동 후 상대 경로로 빌드. - **릴리스 브랜치 이름**: `builds/release` (`builds.release` 아님). - **코드 주석의 `Design Ref: §...`**: 과거 설계 문서 참조이며 해당 문서는 저장소에 없음.