Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extraKnownMarketplaces": {
"claude-plugins-official": {
"source": {
"source": "github",
"repo": "anthropics/claude-plugins-official"
}
}
},
"enabledPlugins": {
"superpowers@claude-plugins-official": true
}
}
4 changes: 4 additions & 0 deletions .github/workflows/dashboard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ on:
- 'tests-projects/LibTestTelemetry/**'
- 'LibCommons/**'
- 'LibNetworks/**'
# 목적: FastPortDashboard.Core가 template-projects/Protos/*.proto로 Echo 메시지를 생성
- 'template-projects/Protos/**'
- 'FastPortSharp.Dashboard.sln'
- '.github/workflows/dashboard.yml'
pull_request:
Expand All @@ -31,6 +33,8 @@ on:
- 'tests-projects/LibTestTelemetry/**'
- 'LibCommons/**'
- 'LibNetworks/**'
# 목적: FastPortDashboard.Core가 template-projects/Protos/*.proto로 Echo 메시지를 생성
- 'template-projects/Protos/**'
- 'FastPortSharp.Dashboard.sln'
- '.github/workflows/dashboard.yml'
workflow_dispatch:
Expand Down
90 changes: 83 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,70 @@
# Agent Instructions (Codex / Claude Code 공통)

LLM 에이전트(Codex, Claude Code 등)가 이 저장소에서 서버 코드를 개발할 때 따르는 규칙이다. 규칙은 이 파일 한 곳에서만 고친다.

## Language

- 기본 응답 언어는 한국어로 한다.
- 사용자가 다른 언어를 명시적으로 요청한 경우에만 해당 언어로 답한다.
- 코드, 명령어, 파일 경로, API 이름, 에러 메시지는 원문을 유지하고, 설명은 한국어로 작성한다.

## Coding Skill Rule
## 개발 워크플로 (superpowers)

- Claude Code는 프로젝트 설정 `.claude/settings.json`으로 `superpowers@claude-plugins-official` 플러그인을 켠다. 작업을 시작하기 전에 상황에 맞는 superpowers 스킬을 먼저 호출하고 그 절차를 따른다.
- 상황별 스킬:

| 상황 | 스킬 |
|---|---|
| 새 기능, 동작 변경, 요구가 모호한 요청의 설계 | `brainstorming` |
| 여러 단계에 걸친 구현 | `writing-plans` → `executing-plans` 또는 `subagent-driven-development` |
| 코드 작성, 버그 수정 | `test-driven-development` (MSTest로 실패하는 테스트를 먼저 만든다) |
| 버그, 테스트 실패, CI 실패의 원인 찾기 | `systematic-debugging` |
| 서로 독립인 작업 여러 개 | `dispatching-parallel-agents` |
| "완료", 커밋, PR 직전 | `verification-before-completion` (빌드·테스트 출력을 직접 확인) |
| 리뷰 요청과 리뷰 반영 | `requesting-code-review`, `receiving-code-review` |
| 작업 브랜치 마무리 | `finishing-a-development-branch` |

- 오타, 문서 한 줄, 설정값 하나처럼 작은 변경은 `brainstorming`·`writing-plans`를 건너뛴다. `verification-before-completion`은 건너뛰지 않는다.
- 산출물 위치: 설계는 `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`, 계획은 `docs/superpowers/plans/YYYY-MM-DD-<feature>.md`에 두고 구현과 같은 PR로 커밋한다. 이 문서들은 결정 기록이고 코드 지도가 아니다. 구현이 끝나면 `docs/llm/` 도메인 문서를 고친다.
- 계획(`writing-plans`)에는 이 파일의 "문서 유지 규칙"과 "변경 시 함께 해야 하는 일"(golden hash 갱신 등)을 단계로 넣는다. 테스트 명령은 `docs/llm/platform.md`의 것을 쓴다.
- `finishing-a-development-branch`에서는 항상 "push 후 PR"을 고른다. `main`은 보호 브랜치라 로컬 머지나 직접 push를 하지 않는다.
- 우선순위: 이 파일(`AGENTS.md`)과 사용자 지시 > superpowers 스킬 > 기본 동작. 예를 들어 스킬 예시의 커밋 메시지(`feat: ...`)보다 아래 "Git / 커밋 메시지" 형식을 따른다.
- 플러그인을 쓸 수 없는 에이전트(Codex 등)는 같은 순서(설계 → 계획 → 테스트 먼저 구현 → 검증 → 리뷰 → PR)를 직접 따른다. 스킬 원문: <https://github.com/obra/superpowers/tree/main/skills>.

## 코드 탐색 규칙

- 코드를 탐색하기 전에 `docs/llm/README.md`를 먼저 읽는다. "도메인 고르기" 표에서 요청에 맞는 도메인 문서 1~2개를 골라, 그 문서의 "작업별 시작점"에 있는 파일만 연다.
- 용어(특히 `BaseSessionClient`/`BaseSessionServer`처럼 이름과 역할이 엇갈리는 것)는 `docs/llm/glossary.md`에서 확인한다.
- 심볼은 이름으로 찾는다. 예: `grep -n "void RequestDisconnect" -r LibNetworks`. 문서에는 줄 번호가 없다.
- `docs/llm/README.md`의 "큰 파일" 표에 있는 파일은 통째로 읽지 않는다. grep으로 위치를 찾고 그 부분만 읽는다. 이미 대화에서 확인한 내용은 다시 읽지 않는다.
- 문서와 코드가 다르면 코드를 믿는다. 작업이 끝나면 문서를 고친다.

## 문서 유지 규칙

- For code writing, editing, refactoring, debugging, test work, and code review, use the `karpathy-guidelines` skill before starting implementation.
- 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.
- 커밋하기 전에 이번 변경이 `docs/llm/` 문서 내용과 맞는지 확인한다.
- 파일·타입·public/protected 멤버·패킷 ID·설정 키·명령어·CI job을 추가, 이동, 삭제, 변경했으면 해당 도메인 문서를 먼저 고친다.
- 문서 수정은 코드 변경과 **같은 커밋**에 넣는다. 코드를 커밋한 뒤 문서를 따로 커밋하지 않는다.
- 수정 기준은 `docs/llm/README.md`의 "문서 유지 규칙"을 따른다.

## Code Map Rule
## C# 코드 스타일

- 코드 탐색 전에 `docs/CODEMAP.md`를 먼저 읽고, 작업에 필요한 파일만 열어 토큰을 절약한다.
- 프로젝트·디렉터리 추가/삭제, 공개 타입 이동, 빌드·테스트 명령 변경처럼 코드맵 내용이 달라지는 변경을 하면 같은 커밋에서 `docs/CODEMAP.md`도 갱신한다.
대상: .NET 10 / C# 14 (`<Nullable>enable</Nullable>`, `<ImplicitUsings>enable</ImplicitUsings>`). 포맷터·분석기 설정 파일(`.editorconfig`)은 아직 없으므로 아래 규칙은 리뷰로 지킨다.

- 네임스페이스는 file-scoped(`namespace LibNetworks.Sessions;`)로 쓴다.
- 새 파일은 UTF-8, LF로 저장한다. 기존 파일의 인코딩은 요청 없이 바꾸지 않는다. 일부 파일(`LibCommons/LatencyStats.cs` 등)은 CP949라서, 다시 저장하면 diff가 커지고 scaffold golden hash가 바뀐다.
- 필드 이름은 **고치는 파일의 기존 규칙을 따른다.** 새 파일은 소속 프로젝트의 규칙을 따른다.
- 엔진·템플릿·샘플(`LibCommons`, `LibNetworks`, `template-projects`, `FastPortServer`, `FastPortClient`): 인스턴스 필드 `m_PascalCase`, static 필드 `s_PascalCase`, 상수 `C_PascalCase` 또는 `PascalCase`.
- 도구·대시보드(`tests-projects/*`, `FastPortDashboard.*`): `_camelCase`.
- 기존 이름을 한꺼번에 바꾸는 리팩터링은 요청이 있을 때만 한다.
- 타입·메서드·프로퍼티·이벤트는 PascalCase, 지역 변수·매개변수는 camelCase로 쓴다. 인터페이스는 `I` 접두어를 붙인다.
- nullable 경고를 `!`로 숨기지 않는다. 불변식으로 null이 아님이 보장될 때만 쓰고 바로 위에 이유 주석을 단다. `#pragma warning disable`도 같은 기준이다.
- 비동기 메서드는 `Task`/`ValueTask`를 반환하고 `async void`를 쓰지 않는다(이벤트 핸들러 제외). `ConfigureAwait(false)`는 고치는 파일의 기존 방식을 따른다(`TimerQueue.cs`는 쓰고 `BaseSession.cs`는 쓰지 않는다). 한 파일 안에서 섞지 않는다.
- `CancellationToken`을 받는 API는 끝까지 전달한다. 취소로 인한 `OperationCanceledException`은 오류 로그로 남기지 않는다.
- 핫 패스(수신·송신·accept 루프)에서는 할당을 늘리지 않는다. `ArrayPool<byte>.Shared`에서 빌린 버퍼는 반환 책임자를 한 곳으로 정하고, 반환 후 다시 쓰지 않는다. 핫 패스에 로그를 추가할 때는 `IsEnabled` 검사로 감싼다.
- 세션당 상태는 해당 세션의 worker Task/잠금 규칙 안에서만 바꾼다. 새 공유 상태를 만들면 어떤 스레드가 읽고 쓰는지 주석으로 적는다.
- 엔진(`LibNetworks`)은 텔레메트리·로깅 구현을 모른다. 관측이 필요하면 `protected virtual OnNetwork*` hook을 추가하고 구현은 앱(예: SmokeServer 세션)에서 override한다.
- 템플릿(`template-projects/FastPortGameServerTemplate`)은 `LibCommons`, `LibNetworks`만 참조한다. `Protocols`, `FastPortServer`, 테스트 프로젝트를 참조하지 않는다.
- 공개 API(엔진의 public/protected 멤버)를 바꾸면 템플릿·샘플·SmokeServer·Dashboard 사용처를 함께 고치고 빌드로 확인한다.

## Commenting Rule

Expand All @@ -26,3 +75,30 @@
- 복잡한 로직은 단계별로 `//` 주석을 나눠서 읽는 사람이 흐름을 따라갈 수 있게 한다.
- 주석은 실제 코드 동작과 일치해야 하며, 변경 시 코드와 함께 갱신한다.
- 의미 없는 반복 설명이나 코드와 모순되는 주석은 작성하지 않는다.

## 테스트 규칙

- 테스트 프레임워크는 MSTest다. 엔진·도구 테스트는 `tests-projects/FastPortTests`, 대시보드 Core 테스트는 `tests-projects/FastPortDashboardTests`에 둔다.
- 테스트 클래스 파일 이름은 대상 타입을 따른다(`<대상>Tests.cs`). 메서드 이름은 영어 `대상_상황_기대결과` 형식으로 쓴다(`BaseSession_InvalidPacketHeaderOnly_DisconnectsWithoutDelivery`).
- `FastPortTests`는 메서드 단위 병렬 실행이다(`MSTestSettings.cs`의 `Parallelize(Scope = ExecutionScope.MethodLevel)`). 고정 포트, 공유 static 상태, 실행 순서 의존을 만들지 않는다. 소켓 테스트는 loopback 포트 0과 기존 `SocketPair` 헬퍼 패턴을 쓴다.
- 비동기 대기는 고정 `Task.Delay` 대신 완료 신호(`TaskCompletionSource`)와 타임아웃으로 기다린다. 타이밍에 따라 흔들리는 단언을 만들지 않는다.
- 버그 수정은 먼저 실패하는 테스트로 재현하고, 수정 후 통과를 확인한다.
- 커밋 전 최소 확인: `dotnet build FastPortSharp.sln -c Release`와 변경 영역 테스트(`--filter`). 엔진을 바꿨으면 `dotnet test FastPortSharp.sln -c Release` 전체를 돌린다. 명령은 `docs/llm/platform.md`의 "빌드·테스트"에 있다.

## 변경 시 함께 해야 하는 일

- `LibCommons/**`, `LibNetworks/**`, `template-projects/FastPortGameServerTemplate/**`, `template-projects/Protos/**`를 고치면(주석만 바꿔도) scaffold golden hash를 갱신한다: `tests/scaffold/run.sh --update-golden case-01-simple` 후 `tests/scaffold/run.sh` 전체 통과를 확인한다.
- `scripts/scaffold-game-server.sh`와 `.ps1`은 같은 결과(바이트 단위)를 내야 한다. 한쪽을 고치면 다른 쪽도 고친다.
- `NetworkDisconnectReason` 값을 추가하면 SmokeServer 세션의 reason 문자열 매핑도 추가한다.
- `.github/workflows/*.yml`의 job `name`을 바꾸면 `main` ruleset 필수 체크 이름도 바꿔야 PR이 머지된다.

## Git / 커밋 메시지

- 작업 브랜치에서 개발하고 PR로 `main`에 머지한다. `main`은 브랜치 보호 대상이다(직접 push 금지, 필수 체크 `build (ubuntu-latest)`, `build (macos-latest)`, `build (windows-latest)`).
- 릴리스 브랜치 이름은 `builds/release`다(`builds.release` 아님). 승격은 `main` → `builds/release` PR로 한다.
- 커밋 author·committer는 `boinred <boinred@outlook.com>`이다.
- 형식은 `<type>(<scope>): <설명>`이다. 커밋 메시지와 PR 제목에 모두 쓴다.
- type: `feat`(기능), `fix`(버그 수정), `perf`(성능), `refactor`(동작 변화 없는 구조 변경), `test`(테스트만), `docs`(문서만), `ci`(워크플로), `chore`(그 밖의 설정·정리).
- scope는 선택이다. 변경이 한 영역에 속하면 넣는다: `buffers`, `packet`, `session`, `listener`, `connector`, `sample`, `template`, `scaffold`, `smoke-server`, `load-runner`, `load-validation`, `telemetry`, `dashboard`, `llm-docs`.
- 설명은 영어 명령형 소문자로 시작하고 첫 줄은 72자 미만, 끝에 마침표를 찍지 않는다.
- 예: `fix(session): guard receive path against malformed headers`, `docs(llm-docs): add session domain map`.
16 changes: 4 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
# CLAUDE.md

공통 에이전트 규칙(언어, 코딩, 주석 규칙)은 `AGENTS.md`에 있고, 저장소 구조는 `docs/CODEMAP.md`에 있다.
Claude Code는 아래 import로 두 파일을 자동으로 읽는다. 규칙은 `AGENTS.md` 한 곳에서만 수정한다.
공통 에이전트 규칙(언어, 코드 탐색, 문서 유지, C# 스타일, 주석, 테스트, 커밋)은 `AGENTS.md`에 있고, 코드 지도는 `docs/llm/`에 있다.
Claude Code는 아래 import로 `AGENTS.md`만 자동으로 읽는다. 코드 지도(`docs/llm/README.md`)는 매 세션 컨텍스트를 아끼려고 import하지 않고, `AGENTS.md`의 "코드 탐색 규칙"에 따라 코드 탐색 전에 직접 읽는다. 규칙은 `AGENTS.md` 한 곳에서만 수정한다.

@AGENTS.md
@docs/CODEMAP.md

## Claude Code 전용 메모

### Git / PR
- 커밋 author·committer: `boinred <boinred@outlook.com>`. `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이 머지됨.
- 커밋에 `Co-Authored-By: Claude` 트레일러를 넣지 않는다.
- 프로젝트 설정 `.claude/settings.json`이 `superpowers@claude-plugins-official` 플러그인을 켠다. 스킬 사용 방식은 `AGENTS.md`의 "개발 워크플로 (superpowers)"를 따르고, 스킬 절차와 `AGENTS.md`가 충돌하면 `AGENTS.md`를 따른다.
2 changes: 1 addition & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ FastPortSharp/
├── 📂 FastPortDashboard.Maui/ # MAUI desktop dashboard (macOS / Windows)
│ # FastPortSharp.Dashboard.sln 로 빌드
│
├── 📂 docs/ # 벤치마크 리포트, runbook, CODEMAP.md
├── 📂 docs/ # 벤치마크 리포트, runbook, llm/ (에이전트용 코드 지도)
└── FastPortSharp.sln
```

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ FastPortSharp/
├── 📂 FastPortDashboard.Maui/ # MAUI desktop dashboard (macOS / Windows)
│ # Built via FastPortSharp.Dashboard.sln
│
├── 📂 docs/ # Benchmark reports, runbooks, CODEMAP.md
├── 📂 docs/ # Benchmark reports, runbooks, llm/ (agent code map)
└── FastPortSharp.sln
```

Expand Down
Loading
Loading