From 0bfd2e0b688f33d1f9662ff043d3f2d1d12969b8 Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 11:58:43 +0900 Subject: [PATCH 1/6] =?UTF-8?q?ui:=20Todo=20=EC=83=81=EC=84=B8=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20push=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=EC=97=90=20interactivePop=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Record/GoalDetail/GoalDetailView.swift | 5 ++++- .../Presentation/HomeTab/Sources/Home/HomeView.swift | 2 +- .../Presentation/HomeTab/Sources/Search/SearchView.swift | 2 +- .../ProfileTab/Sources/Profile/ProfileView.swift | 2 +- Application/Presentation/TodayTab/Sources/TodayView.swift | 6 +++++- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index 4c397c1a..f2689dc4 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -87,7 +87,10 @@ public struct GoalDetailView: View { onUpdate: { store.send(.view(.refresh)) } ) } - .navigationDestination(item: $store.scope(state: \.todoDetail, action: \.todoDetail)) { + .navigationDestination( + item: $store.scope(state: \.todoDetail, action: \.todoDetail), + interactivePop: true + ) { TodoDetailView( store: Store( initialState: TodoDetailFeature.State( diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift index 8d255245..b9ea1206 100644 --- a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift @@ -73,7 +73,7 @@ public struct HomeView: View { interactivePop: { switch $0 { case .category: true - case .todo: false + case .todo: true } }, destination: destinationView diff --git a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift index 710874ba..497682cf 100644 --- a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift +++ b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift @@ -42,7 +42,7 @@ struct SearchView: View { } .background(Color.appBackground.ignoresSafeArea()) .prominentAlert(store, state: \.alert, action: \.alert) - .navigationDestination(for: Path.self) { path in + .navigationDestination(for: Path.self, interactivePop: { _ in true }) { path in switch path { case .todo(let todoId): TodoDetailView(store: Store( diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift index 4481f055..1a1b9f74 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift @@ -63,7 +63,7 @@ public struct ProfileView: View { for: ProfileRoute.self, interactivePop: { switch $0 { - case .settings, .theme: true + case .settings, .theme, .activity, .recentTodo: true default: false } }, diff --git a/Application/Presentation/TodayTab/Sources/TodayView.swift b/Application/Presentation/TodayTab/Sources/TodayView.swift index a24d1fe8..9e7697f1 100644 --- a/Application/Presentation/TodayTab/Sources/TodayView.swift +++ b/Application/Presentation/TodayTab/Sources/TodayView.swift @@ -70,7 +70,11 @@ public struct TodayView: View { .background(Color.appBackground) .refreshable { await store.send(.refresh).finish() } .toolbarVisibility(.hidden, for: .navigationBar) - .navigationDestination(for: TodayRoute.self, destination: destination) + .navigationDestination( + for: TodayRoute.self, + interactivePop: { _ in true }, + destination: destination + ) .sheet(isPresented: $store.isCategoryFilterPresented) { CategoryFilterSheet(store: store) } From 9f39089b261e751396f5bb18165b2b1e031c9875 Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 11:59:42 +0900 Subject: [PATCH 2/6] =?UTF-8?q?ui:=20Todo=20=EC=83=81=EC=84=B8=20=EB=B3=B8?= =?UTF-8?q?=EB=AC=B8=20=EC=B9=B4=EB=93=9C=20=EA=B5=AC=EC=A1=B0=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/TodoDetailContentView.swift | 56 +++++++++++++------ .../Sources/Todo/Detail/PreviewView.swift | 2 +- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Application/Presentation/PresentationShared/Sources/Common/TodoDetailContentView.swift b/Application/Presentation/PresentationShared/Sources/Common/TodoDetailContentView.swift index 4d1d5995..d2cda47f 100644 --- a/Application/Presentation/PresentationShared/Sources/Common/TodoDetailContentView.swift +++ b/Application/Presentation/PresentationShared/Sources/Common/TodoDetailContentView.swift @@ -9,7 +9,6 @@ import SwiftUI import Domain struct TodoDetailContentView: View { - @ScaledMetric(relativeTo: .title3) private var fontSize = 20 let title: String let content: String let referenceItems: [Int: TodoReferenceItem] @@ -17,29 +16,52 @@ struct TodoDetailContentView: View { var onOpenTodoID: ((String) -> Void)? var body: some View { - ZStack { - Color(.systemGroupedBackground).ignoresSafeArea() - VStack(alignment: .leading, spacing: 10) { + ScrollView { + LazyVStack(alignment: .leading, spacing: 20) { ScrollView(.horizontal) { - HStack(alignment: .firstTextBaseline, spacing: 8) { - Text(title) - Text("#\(number)") - .foregroundStyle(.gray) - .fixedSize(horizontal: true, vertical: false) + LazyHStack(alignment: .firstTextBaseline, spacing: 0, pinnedViews: .sectionFooters) { + Section { + Text(title) + } footer: { + Text("#\(number)") + .foregroundStyle(Color.textTertiary) + .padding(.leading, 8) + .background { + Color.appBackground.padding(.trailing, -16) + } + } } .lineLimit(1) .font(.title3.bold()) } - .frame(height: fontSize + 10) + .scrollBounceBehavior(.always, axes: .horizontal) .scrollIndicators(.hidden) - .contentMargins(16, for: .scrollContent) - Divider() - TodoMarkdownContentView( - content: content, - referenceItems: referenceItems, - onOpenTodoID: onOpenTodoID - ) + .contentMargins(.horizontal, 16, for: .scrollContent) + .padding(.horizontal, -16) + + Group { + if content.isEmpty { + ContentUnavailableView( + String( + localized: "development_record_content_empty_title", + bundle: PresentationResources.bundle + ), + systemImage: "doc.text" + ) + } else { + TodoMarkdownContentView( + content: content, + referenceItems: referenceItems, + isScrollEnabled: false, + onOpenTodoID: onOpenTodoID + ) + .frame(minHeight: 120, alignment: .top) + } + } + .padding(.vertical, 16) + .background(Color.surface, in: .rect(cornerRadius: 24)) } + .padding() } } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Detail/PreviewView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Detail/PreviewView.swift index 4d3e50ad..0d575261 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Detail/PreviewView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Detail/PreviewView.swift @@ -13,7 +13,7 @@ struct PreviewView: View { var body: some View { ZStack { - Color(.systemGroupedBackground).ignoresSafeArea() + Color.appBackground.ignoresSafeArea() if let todo = store.todo { TodoDetailContentView( title: todo.title, From be7c5de832287afce5dc54e0f698388a3a26c29e Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 11:59:55 +0900 Subject: [PATCH 3/6] =?UTF-8?q?ui:=20Todo=20=EC=83=81=EC=84=B8=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=ED=83=91=EB=B0=94=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entry/Sources/Root/RootView.swift | 16 +---- .../Sources/PushNotificationListView.swift | 9 +-- .../Sources/Todo/Detail/TodoDetailView.swift | 65 +++++++++++++------ .../Sources/Todo/Editor/TodoEditorView.swift | 24 ------- 4 files changed, 49 insertions(+), 65 deletions(-) diff --git a/Application/Presentation/Entry/Sources/Root/RootView.swift b/Application/Presentation/Entry/Sources/Root/RootView.swift index bb4e709a..23d1e28a 100644 --- a/Application/Presentation/Entry/Sources/Root/RootView.swift +++ b/Application/Presentation/Entry/Sources/Root/RootView.swift @@ -53,9 +53,7 @@ public struct RootView: View { } .prominentAlert(store, state: \.alert, action: \.alert) .sheet(item: $store.scope(state: \.sheet, action: \.sheet)) { sheetStore in - sheetContent(todoId: sheetStore.todoId) { - sheetStore.send(.tapCloseButton) - } + sheetContent(todoId: sheetStore.todoId) } .onReceive(pushNotificationTodoIdPublisher) { todoId in store.send(.presentTodoDetail(todoId)) @@ -63,23 +61,15 @@ public struct RootView: View { } } - private func sheetContent( - todoId: String, - onClose: @escaping () -> Void - ) -> some View { + private func sheetContent(todoId: String) -> some View { NavigationStack { TodoDetailView(store: Store( initialState: TodoDetailFeature.State(todoId: todoId, showEditButton: false) ) { TodoDetailFeature() }) - .toolbar { - ToolbarLeadingButton { - onClose() - } - } } - .background(Color(.systemGroupedBackground)) + .background(Color.appBackground) .presentationDragIndicator(.visible) } } diff --git a/Application/Presentation/NotificationTab/Sources/PushNotificationListView.swift b/Application/Presentation/NotificationTab/Sources/PushNotificationListView.swift index 01dcfe83..121e59e5 100644 --- a/Application/Presentation/NotificationTab/Sources/PushNotificationListView.swift +++ b/Application/Presentation/NotificationTab/Sources/PushNotificationListView.swift @@ -288,14 +288,9 @@ public struct PushNotificationListView: View { ) { TodoDetailFeature() }) - .id(sheetStore.todoId) - .toolbar { - ToolbarLeadingButton { - sheetStore.send(.tapCloseButton) - } - } + .id(sheetStore.todoId) } - .background(Color(.systemGroupedBackground)) + .background(Color.appBackground) .presentationDragIndicator(.visible) } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift index f97292ba..f86cc885 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift @@ -12,6 +12,7 @@ import Core import Domain public struct TodoDetailView: View { + @Environment(\.dismiss) private var dismiss @Environment(\.isTabContentActive) private var isTabContentActive @Environment(\.openWindow) private var openWindow @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @@ -28,7 +29,7 @@ public struct TodoDetailView: View { public var body: some View { ZStack { - Color(.systemGroupedBackground).ignoresSafeArea() + Color.appBackground.ignoresSafeArea() if let todo = store.todo { TodoDetailContentView( title: todo.title, @@ -41,13 +42,14 @@ public struct TodoDetailView: View { LoadingView() } } + .safeAreaInset(edge: .top, spacing: 0) { topBar } + .toolbarVisibility(.hidden, for: .navigationBar) .onAppear { store.send(.onAppear) } .onReceive(windowSubmits) { submit in guard case .update(let value, let todo) = submit, value.matchesEdit(todoId: store.todoId) else { return } store.send(.setTodo(todo)) } - .navigationBarTitleDisplayMode(.inline) .prominentAlert(store, state: \.alert, action: \.alert) .sheet( item: $store.scope(state: \.sheet, action: \.sheet) @@ -61,34 +63,60 @@ public struct TodoDetailView: View { ) { store in fullScreenCoverContent(store) } - .toolbar { toolbarContent } } private var windowSubmits: AnyPublisher { windowEvent?.submits ?? Empty().eraseToAnyPublisher() } - @ToolbarContentBuilder - private var toolbarContent: some ToolbarContent { - ToolbarItem(placement: .topBarTrailing) { + private var topBar: some View { + HStack(spacing: 12) { + NavigationBackButton { dismiss() } + Spacer() + infoButton + if store.showEditButton { + editButton + } + } + .padding(.horizontal) + .padding(.vertical, 12) + .background(Color.appBackground, ignoresSafeAreaEdges: .top) + } + + @ViewBuilder + private var infoButton: some View { + if #available(iOS 26.0, *) { + Button { + store.send(.setSheet(.info)) + } label: { + Image(systemName: "info.circle") + } + .topBarButtonStyle() + } else { Button { store.send(.setSheet(.info)) } label: { Image(systemName: "info.circle") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) } + .adaptiveButtonStyle(shape: .circle, color: .surface, glassEffect: .enabled) } - if store.showEditButton { + } + + @ViewBuilder + private var editButton: some View { + Button { + openTodoEditor() + } label: { if #available(iOS 26.0, *) { - ToolbarSpacer(.fixed, placement: .topBarTrailing) - } - ToolbarItem(placement: .topBarTrailing) { - Button { - openTodoEditor() - } label: { - Text(String(localized: "todo_edit", bundle: PresentationResources.bundle)) - } + Image(systemName: "pencil") + } else { + Text(String(localized: "todo_edit", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.accent) } } + .topBarButtonStyle() } private func openTodoEditor() { @@ -130,14 +158,9 @@ public struct TodoDetailView: View { NavigationStack { if let todoStore = sheetStore.scope(state: \.todoDetail, action: \.todo) { TodoDetailView(store: todoStore) - .toolbar { - ToolbarLeadingButton { - sheetStore.send(.tapCloseButton) - } - } } } - .background(Color(.systemGroupedBackground)) + .background(Color.appBackground) .presentationDragIndicator(.visible) } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 115dd22d..d53b5174 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -100,30 +100,6 @@ public struct TodoEditorView: View { TodoDetailFeature() }) .id(item.id) - .toolbar { - ToolbarItem(placement: .topBarLeading) { - Button { - store.send(.showInspector(.options)) - } label: { - Label( - String( - localized: "todo_options_section", - bundle: PresentationResources.bundle - ), - systemImage: "chevron.left" - ) - } - } - if movesActionsToInspector { - ToolbarItem(placement: .topBarTrailing) { - EditorToolbarActions(store: store, onSubmit: submit) - } - } else { - ToolbarTrailingButton { - store.send(.binding(.set(\.isInspectorPresented, false))) - } - } - } } } } From af8199df187c0dfbc93eb57ddc15378a3acfa1c0 Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 12:50:46 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20Todo=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=9D=B8=EC=8A=A4=ED=8E=99=ED=84=B0=EC=9D=98=20=EB=92=A4?= =?UTF-8?q?=EB=A1=9C=EA=B0=80=EA=B8=B0=EB=A5=BC=20=EC=98=B5=EC=85=98=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B3=B5=EA=B7=80=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Todo/Detail/TodoDetailView.swift | 13 +++++++++++-- .../Sources/Todo/Editor/TodoEditorView.swift | 13 ++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift index f86cc885..a54d7595 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift @@ -18,13 +18,16 @@ public struct TodoDetailView: View { @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @State var store: StoreOf private let windowEvent: TodoEditorWindowEvent? + private let onBack: (() -> Void)? public init( store: StoreOf, - windowEvent: TodoEditorWindowEvent? = nil + windowEvent: TodoEditorWindowEvent? = nil, + onBack: (() -> Void)? = nil ) { self.store = store self.windowEvent = windowEvent + self.onBack = onBack } public var body: some View { @@ -71,7 +74,13 @@ public struct TodoDetailView: View { private var topBar: some View { HStack(spacing: 12) { - NavigationBackButton { dismiss() } + NavigationBackButton { + if let onBack { + onBack() + } else { + dismiss() + } + } Spacer() infoButton if store.showEditButton { diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index d53b5174..f57c781c 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -94,11 +94,14 @@ public struct TodoEditorView: View { } case .todo(let item): NavigationStack { - TodoDetailView(store: Store( - initialState: TodoDetailFeature.State(todoId: item.id, showEditButton: false) - ) { - TodoDetailFeature() - }) + TodoDetailView( + store: Store( + initialState: TodoDetailFeature.State(todoId: item.id, showEditButton: false) + ) { + TodoDetailFeature() + }, + onBack: { store.send(.showInspector(.options)) } + ) .id(item.id) } } From 36a6d70b14a482524bc528aee017318a122281cf Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 12:55:56 +0900 Subject: [PATCH 5/6] =?UTF-8?q?docs:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B4=87=EC=9A=A9=20AGENTS.md=20=EC=A7=80=EC=B9=A8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..99d24009 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,92 @@ +# AGENTS.md + +## Scope + +- This file contains the review guidelines for the Codex GitHub code review bot. +- Working rules for other agents live in `CLAUDE.md` and the Notion page `DevLog Agent Policy`, which are the source of truth. This file is a summary of the rules that matter for review. If the two differ, follow Notion. + +## Review guidelines + +### Language (highest priority) + +- Write every review comment, summary, and question in Korean (한국어). Do not write review text in English, even when the PR title, description, commit messages, or code comments are in English. + - Keep code identifiers, file paths, commands, and quoted source text in their original form. + - Keep the priority badge (`P0` to `P3`) as is, and write the explanation in Korean. + - Do not translate implementation names such as `StorePattern`, `ToastPresenter`, or `MainView`. +- Keep comments concise: one issue per comment, short sentences, and end sentences in Korean noun form where natural (명사형 종결), matching the existing PR style. +- Preferred shape of a comment: + - Title: `[P2] 인스펙터 안의 Todo 상세에서 뒤로가기가 옵션 페이지로 돌아가지 않음` + - Location, trigger, impact, and minimal fix, each on its own line in Korean. + +### Priorities + +- `P0`, `P1`: data loss, security, crashes, concurrency and resource lifetime problems, behavior regressions. +- `P2`: architecture violations, scope drift, missing meaningful tests. +- `P3`: low-impact violations of the repository conventions below. +- Do not report: + - Matters of taste and style that do not affect behavior. + - Formatting-only issues that SwiftLint would catch. + - Speculation that the code does not support. + +### What counts as a finding + +- Report only issues that the code supports and that have a concrete failure scenario. +- For each finding, include: + - The file path and line. + - The condition that triggers it. + - The impact on users or behavior. + - The minimum correction. +- Order findings by severity. Do not repeat the same finding in several places. +- Do not claim that tests or runtime behavior were verified if they were not run. +- Do not raise again threads that are already resolved or feedback that was already applied. + +### Checks for this repository (DevLog_iOS) + +- Behavior preservation: + - Behavior changes that were not requested, and cleanups outside the requested scope. + - New logic written where existing logic could have been reused. +- Architecture: + - No dependency injection between types of the same layer (initializer, stored property, environment, or runtime resolver). + - The only exception is a SwiftUI `View` in `Application/Presentation` receiving same-layer presentation objects such as a ViewModel, Coordinator, or Store. + - `Infra` depends on `Data` and `Core`, not on `Domain`. + - Do not move domain entities to `Core` only because several modules use them. + - Firebase-specific error detection belongs in `Infra`; `Data` handles domain-level errors after mapping. + - Widget UI consumes snapshot data only. `WidgetCore` must not depend on Domain, Data, Infra, Persistence, Presentation, or App. +- StorePattern: + - Keep `@MainActor`, `State`, `Action`, `SideEffect`, and `send -> reduce -> run`. + - Reducers compute state and return side effects; I/O belongs in `run` or injected services. + - Do not add task cancellation or async wrappers around operations that are not actually async. + - Remove reducer-era helper methods left behind after work moved into `run`. +- SwiftUI: + - No intermediate views, properties, or wrappers that only forward to another view. + - Feature-owned presentation state of a Store-backed view lives in the Feature's `State`; do not duplicate it as view-local `@State`. + - View-local `@State` is only for transient rendering and measurement that does not change the feature flow. + - Do not add accessibility code that was not requested, and do not remove existing accessibility behavior without a reason. +- Design tokens: + - UI changes must use the existing `ColorPalette` colors (`Color+Assets`), not hard-coded or system colors. +- Localization: + - Missing keys or translations for new user-facing strings. + - Large unrelated changes in `.xcstrings`. +- Swift conventions (`P3`): + - Explicit type annotations that are not required. + - New Swift file headers whose author is not `opfic`. + - Prefer `<` and `<=` over `>` and `>=` when the meaning is the same. +- Repository rules: + - SwiftUI preview code (`#Preview`, `PreviewProvider`, preview-only fixtures) included in a commit. + - Secrets, tokens, or private configuration files. + - Unnecessary changes to generated Xcode projects or `Package.resolved`. + - A PR title that differs from the title of the linked issue. + - A PR body with sections not declared in the PR template, or with verification results (build, test, lint). + - Tool attribution text (such as `Co-Authored-By` or `Generated with`) in commits or the PR body. + +### Review summary + +- Write the findings first, then, in order: + - Verdict: one of `Pass`, `Block`, `Needs Follow-up`. + - The scope that was inspected. + - Verification that could not be done. + - Limitations. +- `Pass` means no blocking finding in the inspected scope. It does not mean tests were run or runtime behavior was verified. +- If there are no findings, state in Korean that there are none ("지적 없음") together with the inspected scope. +- If required source files could not be read, state the missing prerequisite and do not give `Pass`. +- Final reminder: all of the above output must be written in Korean. From a99d77afc812b0bfccd4896958b6ffe30be9e8b7 Mon Sep 17 00:00:00 2001 From: opficdev Date: Sun, 4 Oct 2026 13:00:02 +0900 Subject: [PATCH 6/6] =?UTF-8?q?docs:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B4=87=20=EC=A7=80=EC=B9=A8=EC=9D=84=20=EC=9E=90?= =?UTF-8?q?=EC=B2=B4=20=EC=99=84=EA=B2=B0=ED=98=95=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 99d24009..be068c13 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,10 @@ ## Scope -- This file contains the review guidelines for the Codex GitHub code review bot. -- Working rules for other agents live in `CLAUDE.md` and the Notion page `DevLog Agent Policy`, which are the source of truth. This file is a summary of the rules that matter for review. If the two differ, follow Notion. +- This file is the only source of rules for the Codex GitHub code review bot in this repository. It is self-contained; do not look for rules in external documents. +- It applies to code review comments on pull requests. It does not describe how to implement or run the project. -## Review guidelines +## Code Review Rules ### Language (highest priority)