From 6446e53df82a73361bf38024bf40294e4c4606ad Mon Sep 17 00:00:00 2001 From: Minjoo Date: Sun, 8 Mar 2026 15:13:11 +0100 Subject: [PATCH 1/4] Update config and guidelines for AI agents --- .gemini/config.yaml | 22 ++++ .gemini/styleguide.md | 238 ++++++++++++++++++++++++++++++++++++++++ AGENTS.md | 246 ++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + 4 files changed, 507 insertions(+) create mode 100644 .gemini/config.yaml create mode 100644 .gemini/styleguide.md create mode 100644 AGENTS.md create mode 120000 CLAUDE.md diff --git a/.gemini/config.yaml b/.gemini/config.yaml new file mode 100644 index 0000000..58d43cd --- /dev/null +++ b/.gemini/config.yaml @@ -0,0 +1,22 @@ +have_fun: false + +code_review: + disable: false + comment_severity_threshold: MEDIUM + max_review_comments: 50 + pull_request_opened: + help: false + summary: true + code_review: true + +ignore_patterns: + # Gradle + - "gradlew" + - "gradlew.bat" + - "gradle/wrapper/**" + + # DB initialization + - "src/main/resources/init.sql" + + # Docs + - "docs/**" diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md new file mode 100644 index 0000000..af1ff68 --- /dev/null +++ b/.gemini/styleguide.md @@ -0,0 +1,238 @@ +# CrewWiki Backend Style Guide + +**Always write all code review comments in Korean.** + +This guide defines the coding conventions for the CrewWiki backend project (Java, Spring Boot, Gradle). +Gemini should flag violations of these rules during code review. + +--- + +## 1. Package Structure + +Each domain must follow this layered structure: + +``` +{domain}/ +├── controller/ +├── dto/ +├── repository/ +└── service/ +``` + +Shared utilities and infrastructure belong under: + +``` +common/ +├── config/ +├── entity/ +├── exception/ +├── infrastructure/ +├── log/ +└── utils/ +``` + +--- + +## 2. Test Code + +### 2.1 Naming + +- `@Nested` classes must be named after the **production method** they test, in **UpperCamelCase**. +- Test method names must follow this format: + - `productionMethod_success_condition` + - `productionMethod_fail_condition` + +**Example:** +```java +@Nested +@DisplayName("Login") +class Login { + @Test + @DisplayName("Login succeeds with valid credentials") + void login_success_byValidCredentials() { } + + @Test + @DisplayName("Login fails with invalid credentials") + void login_fail_byInvalidCredentials() { } +} +``` + +### 2.2 BDD Pattern + +Tests must follow the BDD structure. The `given` block may be omitted if unnecessary: + +```java +// given (omit if not needed) +// when +// then +``` + +### 2.3 Fixtures + +Use static factory methods for test data setup. Do not use constructors directly in tests. + +```java +// Correct +CrewDocument doc = DocumentFixture.createDefaultCrewDocument(); +``` + +### 2.4 Test Strategy + +- Controller tests: use `RestAssured` when authentication/authorization is required. +- Service tests: use `@SpringBootTest` with `WebEnvironment.MOCK` or `WebEnvironment.NONE` (do not start a Tomcat server). +- Use `assertSoftly` when asserting multiple conditions. +- Prefer **state verification** over behavior verification. +- Service tests are **mandatory**. Controller tests are optional (add when needed). + +--- + +## 3. Naming Conventions + +- **Methods**: must start with a verb. Do not include the entity name in the method name. + - Correct: `memberService.findById(Long id)` + - Incorrect: `memberService.getMember(Long id)` + +- **Path variables**: must be specific and descriptive. + - Correct: `/api/{documentId}` + - Incorrect: `/api/{id}` + +- **DTOs**: must use `Request` / `Response` suffixes. + - Registration DTOs may use `Register` instead of `Create`. + - Examples: `DocumentSearchResponse`, `DocumentUpdateRequest` + +--- + +## 4. Object-Oriented Principles + +Apply the following rules as strictly as possible: + +1. Only one level of indentation per method. +2. No `else` keyword. Use early returns instead. +3. Wrap all primitives and strings in meaningful types. +4. Only one dot per line (avoid method chaining across multiple objects). +5. No abbreviations in names. +6. Keep classes small and focused. +7. Maximum **2 instance variables** per class. +8. Use first-class collections (wrap collections in dedicated classes). +9. Use getters and setters only when strictly necessary. + +--- + +## 5. Exception Handling + +All error responses must include an error code: + +```json +{ + "code": "DOCUMENT_NOT_FOUND", + "message": "..." +} +``` + +Do not throw generic exceptions. Use project-defined exception types with error codes. + +--- + +## 6. Annotation Order + +Annotations must follow this order (top to bottom): + +1. Logging (`@Slf4j`) +2. Lombok (`@Getter`, `@NoArgsConstructor`, `@Builder`, etc.) +3. Spring meta (`@EntityListeners`, etc.) +4. Spring component (`@Entity`, `@Table`, `@Service`, `@RestController`, etc.) — always last + +**Example:** +```java +@Slf4j +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@EntityListeners(AuditingEntityListener.class) +@Entity +@Table(name = "...") +public class SampleEntity { } +``` + +--- + +## 7. Domain Exposure + +- Domain objects (entities) must **not** be exposed outside the service layer. +- Controllers must only receive and return DTOs. + +**Correct:** +```java +public ApiResponse> getByUuid(...) { } +``` + +**Incorrect:** +```java +public Document getByUuid(...) { } +``` + +--- + +## 8. API and DTO Mapping + +- Each API endpoint must have its own dedicated DTO (1:1 mapping). +- If the same resource has both admin and general endpoints, use separate DTOs. + +**Example:** +- Admin document search → `AdminDocumentSearchResponse` +- General document search → `DocumentSearchResponse` + +--- + +## 9. Code Style + +- Add one blank line before each class declaration. +- If a method has 2 or more parameters, place each parameter on a new line. +- No restriction on method length; prioritize readability with proper line breaks. + +--- + +## 10. Validation Placement + +- **Behavior validation** (e.g., authorization, business rules): in the service layer. +- **State validation** (e.g., field constraints, invariants): in the domain layer. +- Ambiguous cases should be discussed and agreed upon by the team. + +--- + +## 11. Import Rules + +- Wildcard imports are **not allowed** (`import com.example.*`). +- Follow IntelliJ IDEA default import ordering. +- Static imports are allowed. + +--- + +## 12. Miscellaneous + +- Use `final` for fields and constants. +- Prefer static factory methods over constructors where appropriate. +- Do not use Value Objects (VO) unless explicitly introduced by the team. +- Constants must use `UPPER_SNAKE_CASE`. +- Member ordering within a class: `public` → `protected` → `private`. Getters go at the bottom. + +--- + +## 13. DTO Policy + +- DTOs must use `record` by default. +- Use `class` only when `record` is not compatible (e.g., `@ModelAttribute` binding). + +--- + +## 14. Shared Naming (Project-wide) + +The following names are already standardized and must be used consistently: + +| Type | Name | +|------|------| +| Paged response wrapper | `PagedResponse` | +| Paging request | `PagingRequest` | +| Token info response | `TokenInfoResponse` | +| Auth tokens response | `AuthTokensResponse` | diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..56328f8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,246 @@ +# CrewWiki Backend Style Guide + +This file provides instructions for AI coding agents (Claude Code, Codex, etc.) working on the CrewWiki backend project. + +**Always respond and write comments in Korean.** + +--- + +## Project Overview + +- **Language**: Java +- **Framework**: Spring Boot +- **Build tool**: Gradle +- **Test**: JUnit 5, RestAssured, AssertJ + +--- + +## 1. Package Structure + +Each domain must follow this layered structure: + +``` +{domain}/ +├── controller/ +├── dto/ +├── repository/ +└── service/ +``` + +Shared code belongs under: + +``` +common/ +├── config/ +├── entity/ +├── exception/ +├── infrastructure/ +├── log/ +└── utils/ +``` + +Do not place domain-specific logic inside `common/`. + +--- + +## 2. Test Code + +### 2.1 Naming + +- `@Nested` classes must be named after the **production method** they test, in **UpperCamelCase**. +- Test method names must follow this format: + - `productionMethod_success_condition` + - `productionMethod_fail_condition` + +```java +@Nested +class Login { + @Test + void login_success_byValidCredentials() { } + + @Test + void login_fail_byInvalidCredentials() { } +} +``` + +### 2.2 BDD Pattern + +```java +// given (omit if not needed) +// when +// then +``` + +### 2.3 Fixtures + +Use static factory methods. Do not instantiate test objects with constructors directly. + +```java +CrewDocument doc = DocumentFixture.createDefaultCrewDocument(); +``` + +### 2.4 Test Strategy + +- Controller tests: use `RestAssured` when authentication/authorization is required. +- Service tests: use `@SpringBootTest(webEnvironment = MOCK or NONE)`. Do not start Tomcat. +- Use `assertSoftly` for multiple assertions. +- Prefer **state verification** over behavior (mock) verification. +- Service tests are **mandatory**. Controller tests are optional. + +--- + +## 3. Naming Conventions + +- **Methods**: start with a verb. Do not include the entity name. + - Correct: `findById(Long id)` + - Incorrect: `getMember(Long id)` + +- **Path variables**: be specific. + - Correct: `/api/{documentId}` + - Incorrect: `/api/{id}` + +- **DTOs**: use `Request` / `Response` suffixes. `Register` / `Update` are also acceptable for mutations. + - Examples: `DocumentSearchResponse`, `DocumentUpdateRequest` + +--- + +## 4. Object-Oriented Principles + +Follow these rules strictly when writing or modifying code: + +1. Only one level of indentation per method. +2. No `else`. Use early returns. +3. Wrap primitives and strings in meaningful types. +4. One dot per line — avoid chaining across objects. +5. No abbreviations. +6. Keep classes small and focused. +7. Maximum **2 instance variables** per class. +8. Wrap collections in first-class collection classes. +9. Avoid getters and setters unless strictly needed. + +--- + +## 5. Exception Handling + +- Do not throw generic exceptions (`RuntimeException`, `Exception`). +- Use project-defined exception types that include an error code. +- All error responses must include a `code` field. + +```json +{ + "code": "DOCUMENT_NOT_FOUND", + "message": "..." +} +``` + +--- + +## 6. Annotation Order + +When adding annotations, always use this order (top to bottom): + +1. Logging (`@Slf4j`) +2. Lombok (`@Getter`, `@NoArgsConstructor`, `@Builder`, etc.) +3. Spring meta (`@EntityListeners`, etc.) +4. Spring component (`@Entity`, `@Table`, `@Service`, `@RestController`, etc.) + +```java +@Slf4j +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +@Entity +@Table(name = "...") +public class SampleEntity { } +``` + +--- + +## 7. Domain Exposure + +- Entities must **not** be returned from controllers or exposed outside the service layer. +- Use DTOs at all boundaries. + +```java +// Correct +public ApiResponse> getByUuid(...) { } + +// Incorrect +public Document getByUuid(...) { } +``` + +--- + +## 8. API and DTO Mapping + +- Each API endpoint must map to its own DTO (1:1). +- Separate DTOs for admin and general endpoints. + +``` +Admin document search → AdminDocumentSearchResponse +General document search → DocumentSearchResponse +``` + +--- + +## 9. Code Style + +- Add one blank line before each class declaration. +- If a method has 2 or more parameters, place each on a new line. +- No restriction on method length; prioritize readability. + +--- + +## 10. Validation Placement + +- **Behavior validation** (business rules, authorization): service layer. +- **State validation** (field constraints, invariants): domain layer. + +--- + +## 11. Import Rules + +- No wildcard imports (`import com.example.*`). +- Follow IntelliJ IDEA default ordering. +- Static imports are allowed. + +--- + +## 12. Miscellaneous + +- Use `final` for fields and constants. +- Prefer static factory methods over constructors. +- Constants: `UPPER_SNAKE_CASE`. +- Member ordering: `public` → `protected` → `private`. Getters go at the bottom. +- Do not introduce Value Objects (VO) without team agreement. + +--- + +## 13. DTO Policy + +- Use `record` for DTOs by default. +- Use `class` only when `record` is incompatible (e.g., `@ModelAttribute` binding). + +--- + +## 14. Shared Naming (Do Not Rename) + +These names are standardized across the project. Do not rename or create alternatives: + +| Type | Name | +|------|------| +| Paged response wrapper | `PagedResponse` | +| Paging request | `PagingRequest` | +| Token info response | `TokenInfoResponse` | +| Auth tokens response | `AuthTokensResponse` | + +--- + +## 15. Agent Behavior Guidelines + +- Before making changes, read the relevant domain's existing code to understand patterns in use. +- Do not introduce new libraries or dependencies without explicit instruction. +- When creating a new class, always check if a similar one already exists in `common/`. +- When writing tests, always add a corresponding fixture if one does not exist. +- Do not modify `build.gradle` unless explicitly asked. +- If uncertain about a design decision, leave a `// TODO:` comment explaining the ambiguity rather than guessing. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file From 9512156ae4c8cba01e312788ca9438dffdb67458 Mon Sep 17 00:00:00 2001 From: Minjoo Date: Sun, 8 Mar 2026 15:24:36 +0100 Subject: [PATCH 2/4] Relax instance variable limit rule in AGENTS.md --- AGENTS.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 56328f8..6982c4a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,8 +49,8 @@ Do not place domain-specific logic inside `common/`. - `@Nested` classes must be named after the **production method** they test, in **UpperCamelCase**. - Test method names must follow this format: - - `productionMethod_success_condition` - - `productionMethod_fail_condition` + - `productionMethod_success_condition` + - `productionMethod_fail_condition` ```java @Nested @@ -92,15 +92,15 @@ CrewDocument doc = DocumentFixture.createDefaultCrewDocument(); ## 3. Naming Conventions - **Methods**: start with a verb. Do not include the entity name. - - Correct: `findById(Long id)` - - Incorrect: `getMember(Long id)` + - Correct: `findById(Long id)` + - Incorrect: `getMember(Long id)` - **Path variables**: be specific. - - Correct: `/api/{documentId}` - - Incorrect: `/api/{id}` + - Correct: `/api/{documentId}` + - Incorrect: `/api/{id}` - **DTOs**: use `Request` / `Response` suffixes. `Register` / `Update` are also acceptable for mutations. - - Examples: `DocumentSearchResponse`, `DocumentUpdateRequest` + - Examples: `DocumentSearchResponse`, `DocumentUpdateRequest` --- @@ -114,7 +114,7 @@ Follow these rules strictly when writing or modifying code: 4. One dot per line — avoid chaining across objects. 5. No abbreviations. 6. Keep classes small and focused. -7. Maximum **2 instance variables** per class. +7. Aim to minimize instance variables per class. JPA entities and DTOs may exceed this when necessary (e.g., audit fields, associations). 8. Wrap collections in first-class collection classes. 9. Avoid getters and setters unless strictly needed. From 35ce78ab29da79306f8a515e9636436a61d8ede3 Mon Sep 17 00:00:00 2001 From: Minjoo Date: Sun, 8 Mar 2026 15:36:29 +0100 Subject: [PATCH 3/4] Add comments for gemini config --- .gemini/config.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.gemini/config.yaml b/.gemini/config.yaml index 58d43cd..1301b70 100644 --- a/.gemini/config.yaml +++ b/.gemini/config.yaml @@ -1,22 +1,27 @@ +# Disable playful or humorous responses in review comments have_fun: false code_review: disable: false + # Only comment on meaningful issues to reduce noise comment_severity_threshold: MEDIUM + + # Prevent excessive comments on large PRs max_review_comments: 50 + pull_request_opened: help: false summary: true code_review: true ignore_patterns: - # Gradle + # Gradle wrapper files - "gradlew" - "gradlew.bat" - "gradle/wrapper/**" - # DB initialization + # Database initialization script - "src/main/resources/init.sql" - # Docs + # Documentation - "docs/**" From d2d74d22047922ca56c3610f300e70be9d0b1a1c Mon Sep 17 00:00:00 2001 From: Minjoo Date: Wed, 11 Mar 2026 22:25:00 +0100 Subject: [PATCH 4/4] Change Gemini styleguide to a symlink --- .gemini/styleguide.md | 239 +----------------------------------------- 1 file changed, 1 insertion(+), 238 deletions(-) mode change 100644 => 120000 .gemini/styleguide.md diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md deleted file mode 100644 index af1ff68..0000000 --- a/.gemini/styleguide.md +++ /dev/null @@ -1,238 +0,0 @@ -# CrewWiki Backend Style Guide - -**Always write all code review comments in Korean.** - -This guide defines the coding conventions for the CrewWiki backend project (Java, Spring Boot, Gradle). -Gemini should flag violations of these rules during code review. - ---- - -## 1. Package Structure - -Each domain must follow this layered structure: - -``` -{domain}/ -├── controller/ -├── dto/ -├── repository/ -└── service/ -``` - -Shared utilities and infrastructure belong under: - -``` -common/ -├── config/ -├── entity/ -├── exception/ -├── infrastructure/ -├── log/ -└── utils/ -``` - ---- - -## 2. Test Code - -### 2.1 Naming - -- `@Nested` classes must be named after the **production method** they test, in **UpperCamelCase**. -- Test method names must follow this format: - - `productionMethod_success_condition` - - `productionMethod_fail_condition` - -**Example:** -```java -@Nested -@DisplayName("Login") -class Login { - @Test - @DisplayName("Login succeeds with valid credentials") - void login_success_byValidCredentials() { } - - @Test - @DisplayName("Login fails with invalid credentials") - void login_fail_byInvalidCredentials() { } -} -``` - -### 2.2 BDD Pattern - -Tests must follow the BDD structure. The `given` block may be omitted if unnecessary: - -```java -// given (omit if not needed) -// when -// then -``` - -### 2.3 Fixtures - -Use static factory methods for test data setup. Do not use constructors directly in tests. - -```java -// Correct -CrewDocument doc = DocumentFixture.createDefaultCrewDocument(); -``` - -### 2.4 Test Strategy - -- Controller tests: use `RestAssured` when authentication/authorization is required. -- Service tests: use `@SpringBootTest` with `WebEnvironment.MOCK` or `WebEnvironment.NONE` (do not start a Tomcat server). -- Use `assertSoftly` when asserting multiple conditions. -- Prefer **state verification** over behavior verification. -- Service tests are **mandatory**. Controller tests are optional (add when needed). - ---- - -## 3. Naming Conventions - -- **Methods**: must start with a verb. Do not include the entity name in the method name. - - Correct: `memberService.findById(Long id)` - - Incorrect: `memberService.getMember(Long id)` - -- **Path variables**: must be specific and descriptive. - - Correct: `/api/{documentId}` - - Incorrect: `/api/{id}` - -- **DTOs**: must use `Request` / `Response` suffixes. - - Registration DTOs may use `Register` instead of `Create`. - - Examples: `DocumentSearchResponse`, `DocumentUpdateRequest` - ---- - -## 4. Object-Oriented Principles - -Apply the following rules as strictly as possible: - -1. Only one level of indentation per method. -2. No `else` keyword. Use early returns instead. -3. Wrap all primitives and strings in meaningful types. -4. Only one dot per line (avoid method chaining across multiple objects). -5. No abbreviations in names. -6. Keep classes small and focused. -7. Maximum **2 instance variables** per class. -8. Use first-class collections (wrap collections in dedicated classes). -9. Use getters and setters only when strictly necessary. - ---- - -## 5. Exception Handling - -All error responses must include an error code: - -```json -{ - "code": "DOCUMENT_NOT_FOUND", - "message": "..." -} -``` - -Do not throw generic exceptions. Use project-defined exception types with error codes. - ---- - -## 6. Annotation Order - -Annotations must follow this order (top to bottom): - -1. Logging (`@Slf4j`) -2. Lombok (`@Getter`, `@NoArgsConstructor`, `@Builder`, etc.) -3. Spring meta (`@EntityListeners`, etc.) -4. Spring component (`@Entity`, `@Table`, `@Service`, `@RestController`, etc.) — always last - -**Example:** -```java -@Slf4j -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -@EntityListeners(AuditingEntityListener.class) -@Entity -@Table(name = "...") -public class SampleEntity { } -``` - ---- - -## 7. Domain Exposure - -- Domain objects (entities) must **not** be exposed outside the service layer. -- Controllers must only receive and return DTOs. - -**Correct:** -```java -public ApiResponse> getByUuid(...) { } -``` - -**Incorrect:** -```java -public Document getByUuid(...) { } -``` - ---- - -## 8. API and DTO Mapping - -- Each API endpoint must have its own dedicated DTO (1:1 mapping). -- If the same resource has both admin and general endpoints, use separate DTOs. - -**Example:** -- Admin document search → `AdminDocumentSearchResponse` -- General document search → `DocumentSearchResponse` - ---- - -## 9. Code Style - -- Add one blank line before each class declaration. -- If a method has 2 or more parameters, place each parameter on a new line. -- No restriction on method length; prioritize readability with proper line breaks. - ---- - -## 10. Validation Placement - -- **Behavior validation** (e.g., authorization, business rules): in the service layer. -- **State validation** (e.g., field constraints, invariants): in the domain layer. -- Ambiguous cases should be discussed and agreed upon by the team. - ---- - -## 11. Import Rules - -- Wildcard imports are **not allowed** (`import com.example.*`). -- Follow IntelliJ IDEA default import ordering. -- Static imports are allowed. - ---- - -## 12. Miscellaneous - -- Use `final` for fields and constants. -- Prefer static factory methods over constructors where appropriate. -- Do not use Value Objects (VO) unless explicitly introduced by the team. -- Constants must use `UPPER_SNAKE_CASE`. -- Member ordering within a class: `public` → `protected` → `private`. Getters go at the bottom. - ---- - -## 13. DTO Policy - -- DTOs must use `record` by default. -- Use `class` only when `record` is not compatible (e.g., `@ModelAttribute` binding). - ---- - -## 14. Shared Naming (Project-wide) - -The following names are already standardized and must be used consistently: - -| Type | Name | -|------|------| -| Paged response wrapper | `PagedResponse` | -| Paging request | `PagingRequest` | -| Token info response | `TokenInfoResponse` | -| Auth tokens response | `AuthTokensResponse` | diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/.gemini/styleguide.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file