Skip to content

Navigation3로 전환한다#712

Open
l2hyunwoo wants to merge 2 commits into
developfrom
feature/nav-3-base
Open

Navigation3로 전환한다#712
l2hyunwoo wants to merge 2 commits into
developfrom
feature/nav-3-base

Conversation

@l2hyunwoo
Copy link
Copy Markdown
Collaborator

@l2hyunwoo l2hyunwoo commented Mar 29, 2026

Summary by CodeRabbit

  • New Features
    • 앱 내 네비게이션 시스템 도입: 핵심 네비게이션 모듈, 직렬화 가능한 네비게이션 키들, 호스트 액티비티 추가로 중앙화된 내비게이션 백스택 제공
  • Documentation
    • 대규모 운영/작업 가이드 추가: 레이어별(앱/코어/데이터/도메인/빌드로직/피처) 및 모듈 생성 스킬 문서 통합
  • Chores
    • 네비게이션 라이브러리 버전 및 의존성 추가, 설정 파일에 모듈 등록, 빌드 로직 플러그인 등록 및 IDE 설정 업데이트

@l2hyunwoo l2hyunwoo self-assigned this Mar 29, 2026
@auto-assign auto-assign Bot requested review from boiledeggg and mwy3055 March 29, 2026 01:11
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 29, 2026

Warning

Rate limit exceeded

@l2hyunwoo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 49 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 16 minutes and 49 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f791e4f0-0f9d-416c-9576-c9f55c631127

📥 Commits

Reviewing files that changed from the base of the PR and between 98bbdea and 888ff3d.

📒 Files selected for processing (49)
  • CLAUDE.md
  • app/build.gradle.kts
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt
  • app/src/main/java/com/ku_stacks/ku_ring/di/NavigationModule.kt
  • build-logic/build.gradle.kts
  • build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/Navigation3Plugin.kt
  • core/navigation/.gitignore
  • core/navigation/build.gradle.kts
  • core/navigation/consumer-rules.pro
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/EntryBuilderProvider.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/AppLifecycleKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/MainNavigationKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/UtilityScreenKeys.kt
  • domain/navigation/consumer-rules.pro
  • feature/club/build.gradle.kts
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailActivity.kt
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailEntryBuilder.kt
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingActivity.kt
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingEntryBuilder.kt
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionActivity.kt
  • feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionEntryBuilder.kt
  • feature/edit_departments/build.gradle.kts
  • feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsActivity.kt
  • feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsEntryBuilder.kt
  • feature/edit_subscription/build.gradle.kts
  • feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionActivity.kt
  • feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionEntryBuilder.kt
  • feature/feedback/build.gradle.kts
  • feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackActivity.kt
  • feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackEntryBuilder.kt
  • feature/kuringbot/build.gradle.kts
  • feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotActivity.kt
  • feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotEntryBuilder.kt
  • feature/library/build.gradle.kts
  • feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatActivity.kt
  • feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatEntryBuilder.kt
  • feature/notice_detail/build.gradle.kts
  • feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebActivity.kt
  • feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebEntryBuilder.kt
  • feature/notification/build.gradle.kts
  • feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationActivity.kt
  • feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationEntryBuilder.kt
  • feature/notion/build.gradle.kts
  • feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewActivity.kt
  • feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewEntryBuilder.kt
  • gradle/libs.versions.toml
  • settings.gradle.kts

Walkthrough

이 PR은 프로젝트 전반에 걸친 대규모 문서(AGENTS.md 및 .claude/skills/*)를 추가하고, Navigation3 통합을 위한 플러그인·라이브러리·코어 네비게이션 모듈과 HostActivity/Hilt 바인딩을 도입하며 Kotlin JPS 설정을 소폭 업데이트합니다.

Changes

Cohort / File(s) Summary
문서화 스킬
​.claude/skills/add-data-module/SKILL.md, ​.claude/skills/add-domain-module/SKILL.md, ​.claude/skills/add-feature-module/SKILL.md
데이터/도메인/피처 모듈 생성 절차, 디렉터리·명명 규칙, Hilt DI 및 빌드 검증 체크리스트를 신규 추가.
리포지토리 에이전트 문서
AGENTS.md, .github/AGENTS.md, app/AGENTS.md, build-logic/AGENTS.md
프로젝트 구조·CI/CD·플러그인 아키텍처·운영 가이드 등 에이전트용 운영 문서 대량 추가.
Core 레이어 문서
core/AGENTS.md, core/designsystem/AGENTS.md, core/firebase-messaging/AGENTS.md, core/ui/AGENTS.md
core 모듈 구성, 디자인 시스템, FCM 흐름, 공유 UI 규약 문서화.
Data 레이어 문서
data/AGENTS.md, data/domain/AGENTS.md, data/local/AGENTS.md, data/remote/AGENTS.md
데이터 계층(Repository, Room, Remote, 매퍼 등) 관례 및 모듈별 작업 지침 추가.
Domain·Feature 문서
domain/AGENTS.md, feature/AGENTS.md, feature/auth/AGENTS.md, feature/main/AGENTS.md
도메인/피처 레이어 설계 규약, UseCase·ViewModel·Compose 패턴 문서화.
네비게이션 기능 추가
core/navigation/..., core/navigation/build.gradle.kts, core/navigation/consumer-rules.pro, core/navigation/.gitignore
새 core:navigation 모듈 추가(네비게이션 키 타입·EntryBuilderProvider 인터페이스·consumer rules 포함).
호스트 액티비티 및 DI
app/src/main/java/.../HostActivity.kt, app/src/main/java/.../di/NavigationModule.kt, app/src/main/AndroidManifest.xml
Hilt로 주입되는 EntryBuilderProvider 집합을 사용해 네비게이션 백스택을 구성하는 HostActivity와 multibinding Hilt 모듈 추가, 매니페스트에 액티비티 등록.
빌드 로직: Navigation3 플러그인
build-logic/build.gradle.kts, build-logic/src/main/kotlin/.../Navigation3Plugin.kt
새 Gradle 플러그인 navigation3 등록 및 구현 추가(네비게이션 런타임/뷰 UI/뷰모델 네비게이션 의존성 자동 주입).
버전 카탈로그·설정
gradle/libs.versions.toml, settings.gradle.kts
Navigation3 관련 버전/라이브러리 항목 추가 및 :core:navigation 서브프로젝트 포함.
IDE 설정
.idea/kotlinc.xml
Kotlin JPS 설정 버전 업데이트(2.3.0 → 2.3.20) 및 externalSystemId 추가.
앱 의존성
app/build.gradle.kts
projects.core.navigation, libs.navigation3.runtime, libs.navigation3.ui 의존성 추가.

Sequence Diagram(s)

sequenceDiagram
    participant Host as HostActivity
    participant Hilt as Hilt DI
    participant Providers as EntryBuilderProvider(s)
    participant Nav as core/navigation (NavBackStack / NavDisplay)

    Host->>Hilt: inject Set<EntryBuilderProvider>
    Host->>Providers: iterate & call provide() on EntryProviderScope
    Providers->>Nav: register navigation entries / NavKey handlers
    Host->>Nav: rememberNavBackStack(SplashKey) -> create back stack
    Host->>Nav: render NavDisplay(backStack)
    Host->>Host: onBack -> pop last entry or finish
Loading

Possibly related PRs

Poem

🐰 새 길을 깎아 놓았네
키와 엔트리 모아 길을 잇고
문서 한 장씩 쌓아두니
에이전트들이 길 잃지 않겠지
토끼는 기쁘게 점프한다 🌱

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 'Navigation3로 전환한다'로, 변경사항의 핵심 내용을 명확하게 반영합니다. 이 PR은 Navigation3 라이브러리 도입, 관련 인프라(EntryBuilderProvider, NavKey, HostActivity 등) 구축, 그리고 광범위한 문서화를 포함하고 있으며, 제목이 이러한 주요 변화를 정확히 설명합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/nav-3-base

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (6)
core/ui/AGENTS.md (1)

14-29: 코드 블록에 언어 지정자를 추가하세요.

마크다운 모범 사례에 따라 펜스 코드 블록에 언어를 지정해야 합니다.

📝 제안된 수정
-```
+```text
 ui/
 ├── src/main/
 │   ├── java/com/ku_stacks/ku_ring/ui/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/ui/AGENTS.md` around lines 14 - 29, The fenced code block in
core/ui/AGENTS.md has no language specifier; update the opening fence from ```
to a language-tagged fence (e.g., ```text or ```bash) so the block becomes
```text and preserves formatting/highlighting. Locate the diagram block in
AGENTS.md (the tree listing starting with "ui/") and change the fence there to
include the language specifier.
.claude/skills/add-feature-module/SKILL.md (1)

59-61: 코드 블록에 언어 지정자를 추가하세요.

마크다운 모범 사례에 따라 펜스 코드 블록에 언어를 지정해야 합니다.

📝 제안된 수정
-```
+```text
 feature/{module}/src/main/java/com/ku_stacks/ku_ring/{module}/compose/
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @.claude/skills/add-feature-module/SKILL.md around lines 59 - 61, The fenced
code block that contains the path string
"feature/{module}/src/main/java/com/ku_stacks/ku_ring/{module}/compose/" lacks a
language identifier; update the Markdown fence to include a language (e.g., use
text or bash) so the block follows Markdown best practices and renders
correctly.


</details>

</blockquote></details>
<details>
<summary>.claude/skills/add-domain-module/SKILL.md (1)</summary><blockquote>

`50-54`: **코드 블록에 언어 지정자를 추가하세요.**

마크다운 모범 사례에 따라 펜스 코드 블록에 언어를 지정해야 합니다.


<details>
<summary>📝 제안된 수정</summary>

```diff
-```
+```text
 domain/{moduleName}/src/main/java/com/ku_stacks/ku_ring/domain/{moduleName}/
 ├── repository/
 └── usecase/
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @.claude/skills/add-domain-module/SKILL.md around lines 50 - 54, Update the
fenced code block in SKILL.md so it includes a language identifier (e.g., change
totext) for the directory tree snippet
"domain/{moduleName}/src/main/java/com/ku_stacks/ku_ring/domain/{moduleName}/
├── repository/ └── usecase/"; edit the markdown block in
.claude/skills/add-domain-module/SKILL.md to use ```text (or another appropriate
language) to follow Markdown best practices.


</details>

</blockquote></details>
<details>
<summary>build-logic/AGENTS.md (1)</summary><blockquote>

`142-146`: **플러그인 적용 예시가 중복 적용으로 읽힐 수 있습니다.**

`id("...application")`와 `kuring("application")`를 동시에 제시하면 “둘 다 써야 한다”로 오해될 수 있습니다. 둘 중 하나만 사용하는 예시로 분리해 주세요.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@build-logic/AGENTS.md` around lines 142 - 146, The example shows both
id("com.ku-stacks.ku-ring.convention.application") and kuring("application")
together making it ambiguous that both are required; split into two separate
examples demonstrating each usage independently (one example that applies the
plugin via id("com.ku-stacks.ku-ring.convention.application") and a separate
example that applies it via kuring("application")), and add a brief caption or
comment clarifying that they are alternatives so readers know to use only one
form.
```

</details>

</blockquote></details>
<details>
<summary>data/AGENTS.md (1)</summary><blockquote>

`158-169`: **TypeConverter 예제에 import 명시 권장**

TypeConverter 예제에서 `Json` 객체를 사용하고 있지만 import가 명시되어 있지 않습니다. 명확성을 위해 `kotlinx.serialization.json.Json` import를 추가하면 좋겠습니다.



<details>
<summary>📝 개선 제안</summary>

```diff
 ### 타입 컨버터

 Room에 저장되는 커스텀 타입은 TypeConverter를 사용합니다:

 ```kotlin
 // local/typeconverter/
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.decodeFromString
+
 `@TypeConverter`
 fun fromList(value: List<String>): String = Json.encodeToString(value)
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@data/AGENTS.md` around lines 158 - 169, The TypeConverter examples (functions
fromList and toList annotated with `@TypeConverter`) use Json but don't show the
necessary imports; add imports for kotlinx.serialization.json.Json and the
extension functions kotlinx.serialization.encodeToString and
kotlinx.serialization.decodeFromString at the top of the snippet so the usage of
Json.encodeToString and Json.decodeFromString compiles and is clear.
```

</details>

</blockquote></details>
<details>
<summary>feature/AGENTS.md (1)</summary><blockquote>

`32-57`: **코드 블록 언어 식별자 누락**

Line 32의 fenced code block에 언어 식별자가 지정되어 있지 않습니다. 명확성을 위해 `text` 또는 `plaintext`를 추가하는 것이 좋습니다.



<details>
<summary>📝 수정 제안</summary>

```diff
 ### 표준 피처 모듈 패턴

 각 피처 모듈은 아래 구조를 따릅니다:

-```
+```text
 feature/{module}/
 ├── build.gradle.kts                              # Convention: kuring("view"), kuring("compose")
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @feature/AGENTS.md around lines 32 - 57, The fenced code block showing the
feature/{module}/ tree is missing a language identifier; update the opening
backticks from to a labeled fence (e.g.,text or ```plaintext) so the
snippet is rendered with explicit language/plaintext highlighting—modify the
code block around the tree diagram in AGENTS.md accordingly.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/add-feature-module/SKILL.md:

  • Line 169: The guideline "알파벳 순서를 유지하면서 추가하세요" in SKILL.md doesn't match the
    actual module order in settings.gradle.kts; update SKILL.md to reflect the true
    convention: either remove the alphabetical requirement and state that new
    feature modules should follow the existing order in settings.gradle.kts (listing
    current modules: auth, club, edit_subscription, feedback, library,
    notice_detail, notion, onboarding, splash, main, kuringbot, edit_departments,
    notification) or explicitly document that contributors must reorder
    settings.gradle.kts to alphabetical before adding new modules—choose the former
    to minimize churn and update the SKILL.md sentence accordingly and add a note
    pointing readers to settings.gradle.kts as the source of truth.

In @.idea/kotlinc.xml:

  • Around line 1-7: The PR title "Navigation3로 전환한다" does not match the actual
    changes (only documentation files like AGENTS.md and SKILL.md and an IDE file
    .idea/kotlinc.xml are modified); either update the PR title and description to
    state it's a documentation-only update referencing AGENTS.md and SKILL.md, or
    include the missing Navigation3 migration code (the actual Navigation3-related
    classes/files) in this PR and clearly link them to the docs, or split into two
    PRs and reference the Navigation3 PR from this docs PR so reviewers know the
    relationship.

In @AGENTS.md:

  • Around line 329-331: Update AGENTS.md to stop recommending a hardcoded
    compose-compiler version that conflicts with Kotlin 2.3.20: remove or change the
    guidance around the compose-compiler = '1.4.8' entry in libs.versions.toml
    and instruct to rely on the org.jetbrains.kotlin.plugin.compose plugin being
    synchronized with the Kotlin version (2.3.20) for Kotlin 2.0+, while keeping the
    separate compose-bom = '2026.03.01' recommendation intact; reference the
    compose-compiler key and compose-bom key so readers know which lines to
    update.

In @core/firebase-messaging/AGENTS.md:

  • Around line 48-49: 문서의 onMessageReceived() 호출 조건이 잘못되어 있어 설명을 “포그라운드에서 호출”으로
    한정하고 있으니, 해당 문장(설명)을 “데이터 메시지 수신 시(포그라운드/백그라운드 포함)”로 수정하고, 참고로
    KuringMessagingService.handleIntent()가 mixed 메시지의 notification 헤더를 제거해 Android
    백그라운드에서도 onMessageReceived() 흐름을 보장한다는 한 줄 설명을 덧붙여 onMessageReceived()와
    KuringMessagingService.handleIntent()의 역할 연관을 명시하세요.

In @data/domain/AGENTS.md:

  • Around line 115-116: The code uses the incorrect API
    LocalDateTime.ofEpochSecond(createdAt) for postedAt; replace that call with the
    project's Long.toLocalDateTime() extension (i.e., set postedAt using
    createdAt.toLocalDateTime()) so it compiles and leverages the existing
    DateTimeUtil.kt extension; update the assignment that currently reads postedAt =
    LocalDateTime.ofEpochSecond(createdAt) to use the extension method on createdAt.

In @data/remote/AGENTS.md:

  • Around line 291-305: The example mixes Retrofit-style interface annotations
    and direct constructor injection; update the DI provider in MyModule to match
    one client library: either (A) for Retrofit keep the @GET interface MyService
    and change provideMyService in MyModule to build a Retrofit instance and return
    retrofit.create(MyService::class.java) (use Retrofit.Builder and
    OkHttp/Converter as needed), or (B) for Ktor remove the @GET annotation and
    implement MyService as a concrete class that accepts HttpClient in its
    constructor, then have provideMyService return MyService(httpClient); adjust
    imports and signatures accordingly so MyService and provideMyService are
    consistent with the chosen library.

In @feature/auth/AGENTS.md:

  • Around line 380-382: The document contains conflicting guidance: some examples
    store passwords in state and hardcode error strings while other sections forbid
    both; pick a single policy (preferably: do NOT persist passwords in state and DO
    NOT hardcode user-facing error strings) and update all examples (including the
    email validation snippet using email.isBlank() and !email.contains("@") and the
    sections at lines ~395-407) to follow it: remove any examples that assign
    passwords to persistent state, replace them with transient/input-only handling
    patterns (e.g., show using ephemeral variables or secure input handlers), and
    replace literal strings like "Email is required"/"Invalid email format" with
    references to a central i18n/key constant or message lookup (e.g.,
    ErrorMessages.EMAIL_REQUIRED or t("email.required")) so the doc is consistent.

In @feature/main/AGENTS.md:

  • Around line 221-229: Remove the redundant explicit namespace assignment by
    deleting the line using the property namespace = "com.ku_stacks.ku_ring.main"
    and leave only the setNameSpace("main") call so the module follows the same
    pattern as other feature modules (e.g., where setNameSpace(...) is used without
    a separate namespace property).
  • Around line 316-337: The code uses a non-existent Compose API
    mutableIntState(0) in the MainScreen composable; replace that call with the
    correct mutableIntStateOf(0) where selectedTab is initialized (the variable
    declared as "var selectedTab by remember { mutableIntState(0) }") so the state
    is created with the proper API and compile-time errors are resolved.

Nitpick comments:
In @.claude/skills/add-domain-module/SKILL.md:

  • Around line 50-54: Update the fenced code block in SKILL.md so it includes a
    language identifier (e.g., change totext) for the directory tree snippet
    "domain/{moduleName}/src/main/java/com/ku_stacks/ku_ring/domain/{moduleName}/
    ├── repository/ └── usecase/"; edit the markdown block in
    .claude/skills/add-domain-module/SKILL.md to use ```text (or another appropriate
    language) to follow Markdown best practices.

In @.claude/skills/add-feature-module/SKILL.md:

  • Around line 59-61: The fenced code block that contains the path string
    "feature/{module}/src/main/java/com/ku_stacks/ku_ring/{module}/compose/" lacks a
    language identifier; update the Markdown fence to include a language (e.g., use
    text or bash) so the block follows Markdown best practices and renders
    correctly.

In @build-logic/AGENTS.md:

  • Around line 142-146: The example shows both
    id("com.ku-stacks.ku-ring.convention.application") and kuring("application")
    together making it ambiguous that both are required; split into two separate
    examples demonstrating each usage independently (one example that applies the
    plugin via id("com.ku-stacks.ku-ring.convention.application") and a separate
    example that applies it via kuring("application")), and add a brief caption or
    comment clarifying that they are alternatives so readers know to use only one
    form.

In @core/ui/AGENTS.md:

  • Around line 14-29: The fenced code block in core/ui/AGENTS.md has no language
    specifier; update the opening fence from to a language-tagged fence (e.g.,text or bash) so the block becomes text and preserves
    formatting/highlighting. Locate the diagram block in AGENTS.md (the tree listing
    starting with "ui/") and change the fence there to include the language
    specifier.

In @data/AGENTS.md:

  • Around line 158-169: The TypeConverter examples (functions fromList and toList
    annotated with @TypeConverter) use Json but don't show the necessary imports;
    add imports for kotlinx.serialization.json.Json and the extension functions
    kotlinx.serialization.encodeToString and kotlinx.serialization.decodeFromString
    at the top of the snippet so the usage of Json.encodeToString and
    Json.decodeFromString compiles and is clear.

In @feature/AGENTS.md:

  • Around line 32-57: The fenced code block showing the feature/{module}/ tree is
    missing a language identifier; update the opening backticks from to a labeled fence (e.g.,text or ```plaintext) so the snippet is rendered with
    explicit language/plaintext highlighting—modify the code block around the tree
    diagram in AGENTS.md accordingly.

</details>

<details>
<summary>🪄 Autofix (Beta)</summary>

Fix all unresolved CodeRabbit comments on this PR:

- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `28da52f4-799d-4744-a4db-4fb8eeadd896`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b912be5fbec62c5cf09ba0fbf339c7251598bc1a and 2730b92b3761344814da5e97f0efc705e73ce5ea.

</details>

<details>
<summary>📒 Files selected for processing (21)</summary>

* `.claude/skills/add-data-module/SKILL.md`
* `.claude/skills/add-domain-module/SKILL.md`
* `.claude/skills/add-feature-module/SKILL.md`
* `.github/AGENTS.md`
* `.idea/kotlinc.xml`
* `AGENTS.md`
* `app/AGENTS.md`
* `build-logic/AGENTS.md`
* `core/AGENTS.md`
* `core/designsystem/AGENTS.md`
* `core/firebase-messaging/AGENTS.md`
* `core/ui/AGENTS.md`
* `data/AGENTS.md`
* `data/domain/AGENTS.md`
* `data/local/AGENTS.md`
* `data/remote/AGENTS.md`
* `domain/AGENTS.md`
* `feature/AGENTS.md`
* `feature/auth/AGENTS.md`
* `feature/main/AGENTS.md`
* `gradle/AGENTS.md`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

":feature:{module}",
```

알파벳 순서를 유지하면서 추가하세요.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# settings.gradle.kts의 feature 모듈 블록을 확인하여 정렬 여부를 검증
rg -A 20 '// feature modules' settings.gradle.kts

Repository: ku-ring/KU-Ring-Android

Length of output: 427


문서의 가이드라인이 실제 코드베이스와 일치하지 않음

이 문서의 "알파벳 순서를 유지하면서 추가하세요" 규칙은 settings.gradle.kts의 실제 feature 모듈 순서와 맞지 않습니다. 현재 모듈들이 알파벳순이 아닙니다 (auth, club, edit_subscription, feedback, library, notice_detail, notion, onboarding, splash, main, kuringbot, edit_departments, notification).

다음 중 하나를 선택하세요:

  • 이 가이드라인을 제거하고 현재 관례를 반영하도록 업데이트
  • 실제로 알파벳 순서를 적용하려면 settings.gradle.kts를 정렬하고 이 규칙을 유지
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/add-feature-module/SKILL.md at line 169, The guideline "알파벳
순서를 유지하면서 추가하세요" in SKILL.md doesn't match the actual module order in
settings.gradle.kts; update SKILL.md to reflect the true convention: either
remove the alphabetical requirement and state that new feature modules should
follow the existing order in settings.gradle.kts (listing current modules: auth,
club, edit_subscription, feedback, library, notice_detail, notion, onboarding,
splash, main, kuringbot, edit_departments, notification) or explicitly document
that contributors must reorder settings.gradle.kts to alphabetical before adding
new modules—choose the former to minimize churn and update the SKILL.md sentence
accordingly and add a note pointing readers to settings.gradle.kts as the source
of truth.

Comment thread .idea/kotlinc.xml
Comment thread AGENTS.md
Comment on lines +329 to +331
- `libs.versions.toml`의 `compose-compiler` 버전이 Kotlin 버전과 일치하는지 확인
- 현재: Compose 2026.03.01, Compiler 1.4.8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Kotlin 2.3.x와 호환되는 Jetpack Compose Compiler 버전은 무엇인가요? 공식 Android Developers 또는 Kotlin 문서 기준으로 알려주세요.

💡 Result:

Kotlin 2.3.x와 호환되는 Jetpack Compose Compiler는 Kotlin 2.0 이상부터 Compose Compiler Gradle Plugin(id: "org.jetbrains.kotlin.plugin.compose")을 사용하며, 해당 플러그인의 버전은 Kotlin 버전과 동일하게 사용합니다. 즉, Kotlin 2.3.0의 경우 2.3.0, Kotlin 2.3.10의 경우 2.3.10, Kotlin 2.3.20의 경우 2.3.20 버전의 플러그인을 사용합니다. 이전 방식(kotlinCompilerExtensionVersion)으로 명시적 버전을 지정하는 것은 Kotlin 1.9.x 이하에서만 필요하며, Kotlin 2.0+에서는 플러그인을 통해 자동으로 호환되는 Compose 컴파일러가 제공됩니다. 설정 예시 (build.gradle.kts): plugins { id("org.jetbrains.kotlin.android") version "2.3.20" id("org.jetbrains.kotlin.plugin.compose") version "2.3.20" }

Citations:


🏁 Script executed:

# Check AGENTS.md content around lines 329-331 and context for Kotlin version
sed -n '320,340p' AGENTS.md

Repository: ku-ring/KU-Ring-Android

Length of output: 627


🏁 Script executed:

# Find and read libs.versions.toml to verify actual versions
find . -name "libs.versions.toml" -type f -exec cat {} \;

Repository: ku-ring/KU-Ring-Android

Length of output: 14787


Compose 컴파일러 버전 안내가 오래된 설정을 반영하고 있습니다.

libs.versions.toml에서 compose-compiler = '1.4.8'은 Kotlin 1.9.x 이전 방식으로, Kotlin 2.3.20과는 호환되지 않습니다. Kotlin 2.0 이상에서는 org.jetbrains.kotlin.plugin.compose 플러그인이 Kotlin 버전(2.3.20)과 자동으로 동기화되므로, 이 항목을 제거하거나 AGENTS.md에서 "Kotlin 버전과 동일한 플러그인 사용(2.3.20)"으로 수정해 주세요. compose-bom = '2026.03.01'은 별도의 Compose 라이브러리 BOM으로 유지됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 329 - 331, Update AGENTS.md to stop recommending a
hardcoded compose-compiler version that conflicts with Kotlin 2.3.20: remove or
change the guidance around the `compose-compiler = '1.4.8'` entry in
`libs.versions.toml` and instruct to rely on the
`org.jetbrains.kotlin.plugin.compose` plugin being synchronized with the Kotlin
version (2.3.20) for Kotlin 2.0+, while keeping the separate `compose-bom =
'2026.03.01'` recommendation intact; reference the `compose-compiler` key and
`compose-bom` key so readers know which lines to update.

Comment on lines +48 to +49
앱이 포그라운드 상태일 때 FCM 메시지가 도착하면 호출됩니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

onMessageReceived() 호출 조건 설명이 프로젝트 동작과 어긋납니다.

현재 문구는 “포그라운드에서 호출”로 한정되어 있어 오해를 유발합니다. 이 프로젝트는 mixed 메시지의 notification 헤더를 제거해 백그라운드에서도 데이터 페이로드 처리 흐름을 보장하므로, 호출 조건을 “데이터 메시지 수신 시(포그라운드/백그라운드 포함)”로 명확히 적어주세요.

Based on learnings: KuringMessagingService.handleIntent()는 Mixed 메시지에서 notification 헤더를 제거해 Android 백그라운드에서 onMessageReceived 미호출 문제를 우회합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/firebase-messaging/AGENTS.md` around lines 48 - 49, 문서의
onMessageReceived() 호출 조건이 잘못되어 있어 설명을 “포그라운드에서 호출”으로 한정하고 있으니, 해당 문장(설명)을 “데이터
메시지 수신 시(포그라운드/백그라운드 포함)”로 수정하고, 참고로 KuringMessagingService.handleIntent()가
mixed 메시지의 notification 헤더를 제거해 Android 백그라운드에서도 onMessageReceived() 흐름을 보장한다는 한
줄 설명을 덧붙여 onMessageReceived()와 KuringMessagingService.handleIntent()의 역할 연관을
명시하세요.

Comment thread data/domain/AGENTS.md
Comment on lines +115 to +116
postedAt = LocalDateTime.ofEpochSecond(createdAt),
imageUrl = imageUrl,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the AGENTS.md file
find . -name "AGENTS.md" -type f | head -20

Repository: ku-ring/KU-Ring-Android

Length of output: 437


🏁 Script executed:

# Check if the file exists and read the context around lines 115-116
if [ -f "data/domain/AGENTS.md" ]; then
  cat -n "data/domain/AGENTS.md" | sed -n '110,120p'
else
  echo "File not found at data/domain/AGENTS.md"
  find . -name "*.md" -path "*/domain/*" | head -10
fi

Repository: ku-ring/KU-Ring-Android

Length of output: 447


🏁 Script executed:

# Search for LocalDateTime usage patterns in the codebase
rg "LocalDateTime\." --max-count=20 -B 2 -A 2

Repository: ku-ring/KU-Ring-Android

Length of output: 15576


🏁 Script executed:

# Check if there are any utility extensions or custom methods for LocalDateTime
rg "fun.*LocalDateTime\|extension.*LocalDateTime\|ofEpochSecond" --max-count=20

Repository: ku-ring/KU-Ring-Android

Length of output: 49


🏁 Script executed:

cat -n core/util/src/main/java/com/ku_stacks/ku_ring/util/DateTimeUtil.kt

Repository: ku-ring/KU-Ring-Android

Length of output: 760


🏁 Script executed:

# Also check if there are any other alternative implementations
find . -name "*DateTimeUtil*" -o -name "*TimeUtil*" | grep -v ".git" | head -10

Repository: ku-ring/KU-Ring-Android

Length of output: 210


LocalDateTime.ofEpochSecond(createdAt) API 시그니처가 잘못되었습니다.

현재 예시는 그대로 복사하면 컴파일되지 않습니다. 이 프로젝트에는 이미 Long.toLocalDateTime() 확장 함수가 core/util/src/main/java/com/ku_stacks/ku_ring/util/DateTimeUtil.kt에 정의되어 있으므로, 이를 사용하세요.

수정 예시
-        postedAt = LocalDateTime.ofEpochSecond(createdAt),
+        postedAt = createdAt.toLocalDateTime(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
postedAt = LocalDateTime.ofEpochSecond(createdAt),
imageUrl = imageUrl,
postedAt = createdAt.toLocalDateTime(),
imageUrl = imageUrl,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@data/domain/AGENTS.md` around lines 115 - 116, The code uses the incorrect
API LocalDateTime.ofEpochSecond(createdAt) for postedAt; replace that call with
the project's Long.toLocalDateTime() extension (i.e., set postedAt using
createdAt.toLocalDateTime()) so it compiles and leverages the existing
DateTimeUtil.kt extension; update the assignment that currently reads postedAt =
LocalDateTime.ofEpochSecond(createdAt) to use the extension method on createdAt.

Comment thread data/remote/AGENTS.md
Comment on lines +291 to +305
interface MyService {
@GET("/api/my-endpoint")
suspend fun getData(): MyResponse
}
```
5. `di/MyModule.kt`에 Hilt 모듈 생성:
```kotlin
@Module
@InstallIn(SingletonComponent::class)
object MyModule {
@Provides
@Singleton
fun provideMyService(httpClient: HttpClient): MyService {
return MyService(httpClient)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and check its structure
if [ -f "data/remote/AGENTS.md" ]; then
  # Get total lines to understand file size
  wc -l data/remote/AGENTS.md
  # Read the specific section mentioned (lines 291-305)
  sed -n '285,310p' data/remote/AGENTS.md
else
  echo "File not found"
fi

Repository: ku-ring/KU-Ring-Android

Length of output: 671


🏁 Script executed:

# Check project dependencies to understand which HTTP library is used
find . -name "build.gradle" -o -name "build.gradle.kts" | head -5

Repository: ku-ring/KU-Ring-Android

Length of output: 206


🏁 Script executed:

# Check app/build.gradle.kts for dependencies
echo "=== Checking app/build.gradle.kts ===" 
wc -l app/build.gradle.kts
head -100 app/build.gradle.kts

# Also check root build.gradle.kts for dependency management
echo -e "\n=== Checking root build.gradle.kts ===" 
cat build.gradle.kts | grep -i "retrofit\|ktor" -A 2 -B 2

Repository: ku-ring/KU-Ring-Android

Length of output: 3476


🏁 Script executed:

# Search for Retrofit and Ktor in all gradle files
echo "=== Searching for Retrofit ===" 
rg "retrofit" . --type gradle -i

echo -e "\n=== Searching for Ktor ===" 
rg "ktor" . --type gradle -i

# Also check for version catalogs
echo -e "\n=== Checking for gradle version catalogs ===" 
find . -name "libs.versions.toml" -o -name "gradle.properties" | xargs grep -i "retrofit\|ktor" 2>/dev/null || echo "No matches in catalogs"

Repository: ku-ring/KU-Ring-Android

Length of output: 1503


@get 데코레이터(Retrofit)와 생성자 주입(Ktor) 패턴이 호환되지 않습니다.

Retrofit의 @GET 인터페이스는 Retrofit.create(MyService::class.java)로 프록시 인스턴스를 생성해야 하며, MyService(httpClient) 직접 호출은 불가능합니다. 프로젝트가 Retrofit과 Ktor을 모두 사용 중이므로, 예시를 하나의 라이브러리에 맞춰 수정해주세요.

  • Retrofit 방식: Retrofit.Builder()...build().create(MyService::class.java)
  • Ktor 방식: @GET 제거하고 구체적 클래스로 변경
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@data/remote/AGENTS.md` around lines 291 - 305, The example mixes
Retrofit-style interface annotations and direct constructor injection; update
the DI provider in MyModule to match one client library: either (A) for Retrofit
keep the `@GET` interface MyService and change provideMyService in MyModule to
build a Retrofit instance and return retrofit.create(MyService::class.java) (use
Retrofit.Builder and OkHttp/Converter as needed), or (B) for Ktor remove the
`@GET` annotation and implement MyService as a concrete class that accepts
HttpClient in its constructor, then have provideMyService return
MyService(httpClient); adjust imports and signatures accordingly so MyService
and provideMyService are consistent with the chosen library.

Comment thread feature/auth/AGENTS.md
Comment on lines +380 to +382
email.isBlank() -> "Email is required"
!email.contains("@") -> "Invalid email format"
else -> null
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

문서 내 가이드가 상충됩니다(비밀번호 상태 보관/에러 문자열 하드코딩).

동일 문서에서 비밀번호를 state에 보관하는 예시와 “state에 저장하지 말라” 지침이 동시에 존재하고, 에러 문자열도 하드코딩 예시와 금지 지침이 충돌합니다. 한 가지 정책으로 통일해 주세요.

Also applies to: 395-407

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@feature/auth/AGENTS.md` around lines 380 - 382, The document contains
conflicting guidance: some examples store passwords in state and hardcode error
strings while other sections forbid both; pick a single policy (preferably: do
NOT persist passwords in state and DO NOT hardcode user-facing error strings)
and update all examples (including the email validation snippet using
email.isBlank() and !email.contains("@") and the sections at lines ~395-407) to
follow it: remove any examples that assign passwords to persistent state,
replace them with transient/input-only handling patterns (e.g., show using
ephemeral variables or secure input handlers), and replace literal strings like
"Email is required"/"Invalid email format" with references to a central i18n/key
constant or message lookup (e.g., ErrorMessages.EMAIL_REQUIRED or
t("email.required")) so the doc is consistent.

Comment thread feature/main/AGENTS.md
Comment on lines +221 to +229
android {
setNameSpace("main")
namespace = "com.ku_stacks.ku_ring.main"

defaultConfig {
manifestPlaceholders["naverClientId"] =
properties["naver.client.id"] as String
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check how setNameSpace is used in other feature modules to verify the pattern

# Find all feature module build.gradle.kts files and check for setNameSpace + namespace usage
rg -A5 -B2 'setNameSpace' --type kotlin --glob '**/feature/**/build.gradle.kts'

Repository: ku-ring/KU-Ring-Android

Length of output: 9068


namespace 명시적 설정 제거 필요

feature/main 모듈은 setNameSpace("main")을 호출한 후 별도로 namespace = "com.ku_stacks.ku_ring.main"을 설정하고 있습니다. 다른 모든 feature 모듈들(splash, onboarding, notion, notification, notice_detail, kuringbot, library, auth, club, feedback, edit_departments)은 setNameSpace()만 사용하고 있으므로, namespace = 라인은 제거하여 일관성을 맞춰주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@feature/main/AGENTS.md` around lines 221 - 229, Remove the redundant explicit
namespace assignment by deleting the line using the property namespace =
"com.ku_stacks.ku_ring.main" and leave only the setNameSpace("main") call so the
module follows the same pattern as other feature modules (e.g., where
setNameSpace(...) is used without a separate namespace property).

Comment thread feature/main/AGENTS.md
Comment on lines +316 to +337
```kotlin
@Composable
fun MainScreen(viewModel: MainViewModel = hiltViewModel()) {
var selectedTab by remember { mutableIntState(0) }

Scaffold(
bottomBar = {
NavigationBar {
NoticeTab(selected = selectedTab == 0, onClick = { selectedTab = 0 })
ArchiveTab(selected = selectedTab == 1, onClick = { selectedTab = 1 })
// ... 추가 탭
}
}
) { padding ->
when (selectedTab) {
0 -> NoticeListScreen()
1 -> ArchiveScreen()
// ... 추가 화면
}
}
}
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if mutableIntStateOf is the correct API in the project

# Search for actual usage patterns in the codebase
rg -n 'mutableIntStateOf|mutableStateOf' --type kotlin -C2

# Also check if mutableIntState exists (it shouldn't)
rg -n 'mutableIntState\(' --type kotlin

Repository: ku-ring/KU-Ring-Android

Length of output: 50380


🏁 Script executed:

# Check Compose runtime imports to understand available APIs
fd -e kt -e java | head -20 | xargs grep -l "androidx.compose.runtime" | head -3 | xargs head -30

# Verify the correct API by looking at one concrete implementation
cat feature/main/src/main/java/com/ku_stacks/ku_ring/main/archive/compose/components/DeleteArchivedNoticesAlertDialog.kt | head -30

Repository: ku-ring/KU-Ring-Android

Length of output: 1358


Compose API 사용법 수정 필요

Line 319의 mutableIntState(0)은 존재하지 않는 API입니다. 최신 Compose에서는 mutableIntStateOf(0)을 사용해야 합니다.

🔧 수정 제안
 `@Composable`
 fun MainScreen(viewModel: MainViewModel = hiltViewModel()) {
-    var selectedTab by remember { mutableIntState(0) }
+    var selectedTab by remember { mutableIntStateOf(0) }

     Scaffold(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@feature/main/AGENTS.md` around lines 316 - 337, The code uses a non-existent
Compose API `mutableIntState(0)` in the MainScreen composable; replace that call
with the correct `mutableIntStateOf(0)` where `selectedTab` is initialized (the
variable declared as "var selectedTab by remember { mutableIntState(0) }") so
the state is created with the proper API and compile-time errors are resolved.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt (1)

23-31: KuringCompositionLocalProvider 래핑 검토 필요

학습된 패턴에 따르면 피처 스크린들은 KuringCompositionLocalProvider로 감싸서 테마, 애널리틱스, 공유 상태를 CompositionLocal로 주입해야 합니다. NavDisplay 컨텐츠를 해당 Provider로 감싸는 것을 고려해 주세요.

♻️ CompositionLocalProvider 래핑 제안
setContent {
    KuringCompositionLocalProvider {
        val backStack = rememberNavBackStack(SplashKey)
        NavDisplay(
            backStack = backStack,
            onBack = { if (backStack.removeLastOrNull() == null) finish() },
            entryProvider = entryProvider {
                entryBuilders.forEach { builder -> with(builder) { provide() } }
            }
        )
    }
}

Based on learnings: "KuringCompositionLocalProvider must wrap feature screens to inject theme, analytics, and shared state via CompositionLocal"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt` around lines 23 -
31, Wrap the NavDisplay content in KuringCompositionLocalProvider inside
setContent so feature screens receive theme, analytics, and shared state via
CompositionLocal; locate the setContent block that creates val backStack =
rememberNavBackStack(SplashKey) and change it so KuringCompositionLocalProvider
{ ... } encloses the backStack creation and the NavDisplay call (onBack and
entryProvider remain unchanged), ensuring all child composables are provided the
CompositionLocals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt`:
- Around line 23-31: The app initializes the nav back stack with SplashKey via
rememberNavBackStack(SplashKey) but entryBuilders (provided by
NavigationModule's `@Multibinds`) can be empty so no entry for SplashKey is
registered, yielding a blank screen; implement and bind an EntryBuilderProvider
that constructs and registers the SplashKey entry (i.e., create an
EntryBuilderProvider implementation that builds the SplashKey entry UI and add
it to the Multibind set used by entryBuilders), ensure it is included by the
entryProvider used in HostActivity's NavDisplay so
rememberNavBackStack(SplashKey) has a corresponding entry.

In
`@core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt`:
- Around line 6-12: NoticeWebKey's id is declared as String but must match the
Int type used by WebViewNotice.id and NoticeDetailRoute.NoticeWeb.id; update the
`@Serializable` data class NoticeWebKey to use val id: Int (or, if string is
intentional, add explicit mapping/parse logic wherever NoticeWebKey is
constructed/serialized to consistently convert between String and Int) so that
the types are consistent with WebViewNotice and NoticeDetailRoute and avoid
parsing/serialization errors.

---

Nitpick comments:
In `@app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt`:
- Around line 23-31: Wrap the NavDisplay content in
KuringCompositionLocalProvider inside setContent so feature screens receive
theme, analytics, and shared state via CompositionLocal; locate the setContent
block that creates val backStack = rememberNavBackStack(SplashKey) and change it
so KuringCompositionLocalProvider { ... } encloses the backStack creation and
the NavDisplay call (onBack and entryProvider remain unchanged), ensuring all
child composables are provided the CompositionLocals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae3a7d64-305c-41a0-b9cd-7f88e55cff3e

📥 Commits

Reviewing files that changed from the base of the PR and between 2730b92 and 98bbdea.

📒 Files selected for processing (17)
  • app/build.gradle.kts
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt
  • app/src/main/java/com/ku_stacks/ku_ring/di/NavigationModule.kt
  • build-logic/build.gradle.kts
  • build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/Navigation3Plugin.kt
  • core/navigation/.gitignore
  • core/navigation/build.gradle.kts
  • core/navigation/consumer-rules.pro
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/EntryBuilderProvider.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/AppLifecycleKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/MainNavigationKeys.kt
  • core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/UtilityScreenKeys.kt
  • domain/navigation/consumer-rules.pro
  • gradle/libs.versions.toml
  • settings.gradle.kts
✅ Files skipped from review due to trivial changes (6)
  • core/navigation/.gitignore
  • core/navigation/consumer-rules.pro
  • app/build.gradle.kts
  • app/src/main/AndroidManifest.xml
  • settings.gradle.kts
  • gradle/libs.versions.toml

Comment on lines +23 to +31
setContent {
val backStack = rememberNavBackStack(SplashKey)
NavDisplay(
backStack = backStack,
onBack = { if (backStack.removeLastOrNull() == null) finish() },
entryProvider = entryProvider {
entryBuilders.forEach { builder -> with(builder) { provide() } }
}
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

SplashKey에 대응하는 엔트리가 없으면 앱이 빈 화면을 표시합니다.

rememberNavBackStack(SplashKey)로 백스택을 초기화하지만, NavigationModule@Multibinds만으로는 entryBuilders가 빈 Set입니다. 따라서 entryProvider 내에서 아무 엔트리도 등록되지 않아 SplashKey에 대한 UI가 렌더링되지 않습니다.

SplashKey를 처리하는 EntryBuilderProvider 구현체가 반드시 필요합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/ku_stacks/ku_ring/HostActivity.kt` around lines 23 -
31, The app initializes the nav back stack with SplashKey via
rememberNavBackStack(SplashKey) but entryBuilders (provided by
NavigationModule's `@Multibinds`) can be empty so no entry for SplashKey is
registered, yielding a blank screen; implement and bind an EntryBuilderProvider
that constructs and registers the SplashKey entry (i.e., create an
EntryBuilderProvider implementation that builds the SplashKey entry UI and add
it to the Multibind set used by entryBuilders), ensure it is included by the
entryProvider used in HostActivity's NavDisplay so
rememberNavBackStack(SplashKey) has a corresponding entry.

Comment on lines +6 to +12
@Serializable data class NoticeWebKey(
val url: String,
val articleId: String,
val id: String,
val category: String,
val subject: String,
) : NavKey
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

id 필드 타입 불일치: String vs Int

NoticeWebKey.idString 타입으로 선언되었지만, 기존 WebViewNotice.idNoticeDetailRoute.NoticeWeb.id는 모두 Int 타입입니다(data/domain/src/main/java/com/ku_stacks/ku_ring/domain/WebViewNotice.ktdomain/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/NoticeDetailRoute.kt 참조).

이 불일치로 인해 변환 시 파싱 오류가 발생하거나 데이터 손실이 있을 수 있습니다. URL 직렬화를 위해 의도적으로 String을 사용한 경우라도, 매핑 로직에서 일관성 있게 처리해야 합니다.

🔧 Int 타입으로 일관성 유지 제안
 `@Serializable` data class NoticeWebKey(
     val url: String,
     val articleId: String,
-    val id: String,
+    val id: Int,
     val category: String,
     val subject: String,
 ) : NavKey
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Serializable data class NoticeWebKey(
val url: String,
val articleId: String,
val id: String,
val category: String,
val subject: String,
) : NavKey
`@Serializable` data class NoticeWebKey(
val url: String,
val articleId: String,
val id: Int,
val category: String,
val subject: String,
) : NavKey
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt`
around lines 6 - 12, NoticeWebKey's id is declared as String but must match the
Int type used by WebViewNotice.id and NoticeDetailRoute.NoticeWeb.id; update the
`@Serializable` data class NoticeWebKey to use val id: Int (or, if string is
intentional, add explicit mapping/parse logic wherever NoticeWebKey is
constructed/serialized to consistently convert between String and Int) so that
the types are consistent with WebViewNotice and NoticeDetailRoute and avoid
parsing/serialization errors.

* chore: Nav3 의존성 추가

* chore: app 모듈에 nav3 의존성 추가

* feat: core-navigation 모듈 추가

* feat: NavKeys, EntryBuilderProvider 추가

* feat: HostActivity, NavigationModule 추가

* chore: 코드리뷰 반영
* feat: EntryBuilder pattern 적용

* docs: add CLAUDE.md

* feat: NoticeWeb쪽과 Club쪽 피쳐에 EntryBuilder 패턴 추가
@l2hyunwoo l2hyunwoo force-pushed the feature/nav-3-base branch from 45455e9 to 888ff3d Compare March 29, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant