{"projects":[{"id":"19d5b0561a88","name":"budget-book","root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","remote":"git@github.com-kdh92:AIVA-SaaS/budget-book.git","tech_stack":["kotlin","spring-boot","flutter","postgresql"],"status":"active"},{"id":"ba061b902a0a","name":"tiggle","root":"/Users/kdh/kdh/github/tiggle","remote":"git@github.com-kdh92:kdh-92/Tiggle.git","tech_stack":["spring-boot","flutter","mysql"],"status":"active"},{"id":"e58345f4e56c","name":"calynda","root":"/Users/kdh/kdh/github/calynda","remote":"https://github.com/calynda-app/calynda-infra.git","tech_stack":["spring-boot","flutter","mysql","kotlin"],"status":"active"}],"gates":[{"project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","tags":["amount_calculation","filter_propagation","db_schema","ui_pattern"],"verdict":"STRUCTURAL_FIX_REQUIRED","acknowledged":true,"created_at":"2026-04-21T14:44:40.456804","recurrence_exit_code":2,"acknowledged_at":"2026-04-21T14:47:46.299548","structural_fix_plan":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book/docs/sessions/2026-04-21_1_plan.md"},{"project_name":"harness","project_root":"/Users/kdh/.claude/harness","tags":["ui_pattern","meta_process"],"verdict":"WARNING","acknowledged":false,"created_at":"2026-04-17T17:08:22.827941","recurrence_exit_code":1},{"project_name":"roouty-ops-assistant","project_root":"/Users/kdh/wemeet/roouty/roouty-ops-assistant","tags":["navigation_state","filter_propagation","amount_calculation","ui_pattern","db_schema","meta_process"],"verdict":"OK","acknowledged":false,"created_at":"2026-04-20T15:22:10.111002","recurrence_exit_code":0},{"project_name":"wemeet-b2b-backend","project_root":"/Users/kdh/wemeet/roouty/wemeet-b2b-backend","tags":["db_schema","ui_pattern"],"verdict":"OK","acknowledged":false,"created_at":"2026-04-21T15:16:52.925114","recurrence_exit_code":0}],"patterns":{"amount_calculation":{"description":"금액 합계/집계 변경 — 모든 서비스에서 동일 기준 적용 필수","grep_patterns":["totalExpense|totalIncome|totalAmount|totalSpent|totalBudget","sumOf|SUM\\(.*amount\\)|sumBy|sumAmount","transferOut|transferIn|transferTotal","balance|잔액|합계|집계"],"file_scopes":["backend/src/main/kotlin/**/*Service.kt","backend/src/main/java/**/*Service.java","be/src/main/kotlin/**/*Service.kt","be/src/main/java/**/*Service.java","frontend/lib/**/bloc/*.dart","frontend/lib/**/widgets/*summary*.dart","frontend/lib/**/widgets/*bar*.dart","fe/lib/**/bloc/*.dart","fe/lib/**/widgets/*summary*.dart","fe/lib/**/widgets/*bar*.dart"],"cross_check":"동일 기간에 대해 모든 API가 동일한 총액을 반환해야 함","known_pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"]},"filter_propagation":{"description":"필터 파라미터가 Event→BLoC→Repository→DataSource→API 전체 체인을 관통해야 함","grep_patterns":["dateFrom|dateTo|categoryId|paymentMethodId|pocketId","amountMin|amountMax|keyword|visibility|type","queryParameters|queryParams|RequestParam"],"file_scopes":["frontend/lib/**/bloc/*_event.dart","frontend/lib/**/bloc/*_bloc.dart","frontend/lib/**/domain/repositories/*.dart","frontend/lib/**/data/repositories/*_impl.dart","frontend/lib/**/data/datasources/*_remote_datasource.dart","fe/lib/**/bloc/*_event.dart","fe/lib/**/bloc/*_bloc.dart","fe/lib/**/domain/repositories/*.dart","fe/lib/**/data/repositories/*_impl.dart","fe/lib/**/data/datasources/*_remote_datasource.dart","backend/src/main/kotlin/**/controller/*.kt","backend/src/main/java/**/controller/*.java","be/src/main/kotlin/**/controller/*.kt","be/src/main/java/**/controller/*.java"],"chain_check":"각 필터 파라미터가 Event → BLoC → Repository → DataSource → API 전체를 관통하는지 확인","known_pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"]},"navigation_state":{"description":"화면 이동 시 현재 상태(year/month/필터 등)가 전달되어야 함","grep_patterns":["context\\.push|context\\.go|context\\.pushNamed","GoRoute|goBranch|shell\\.goBranch"],"file_scopes":["frontend/lib/**/pages/*.dart","frontend/lib/**/widgets/*.dart","frontend/lib/core/router/*.dart","fe/lib/**/pages/*.dart","fe/lib/**/widgets/*.dart","fe/lib/core/router/*.dart"],"cross_check":"목적지 페이지로 이동하는 모든 경로에서 동일한 상태 파라미터가 전달되는지","known_pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"]},"ui_pattern":{"description":"공통 위젯/UI 패턴 변경 시 모든 사용처에 동일 적용","grep_patterns":["UnifiedFilterBar|MonthSummaryBar|MonthNavigator","CardPendingSummary|CategoryGroupSelector|EmptyStateWidget"],"file_scopes":["frontend/lib/core/widgets/**/*.dart","frontend/lib/**/pages/*.dart","frontend/lib/**/widgets/*.dart","fe/lib/core/widgets/**/*.dart","fe/lib/**/pages/*.dart","fe/lib/**/widgets/*.dart"],"cross_check":"위젯 시그니처 변경 시 모든 호출처가 업데이트되었는지","known_pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"]},"meta_process":{"description":"하네스/프로세스 자체의 적용 여부 검증 — 도구가 존재해도 프로토콜에 연결되지 않으면 무용지물","grep_patterns":["pre-change-audit|scope-audit|recurrence_check","lessons-learned|audit-patterns","CLAUDE\\.md|Step 1\\.5"],"file_scopes":[".claude/CLAUDE.md",".claude/harness/**/*.sh",".claude/harness/**/*.py",".claude/harness/**/*.json"],"cross_check":"도구 생성 시 CLAUDE.md 프로토콜에 강제 단계로 삽입되었는지, MEMORY.md에 등록되었는지","known_pitfalls":["도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음","메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름"]},"db_schema":{"description":"DB 스키마 변경 시 관련 코드 전체 업데이트","grep_patterns":["CHECK|CONSTRAINT|UNIQUE|INDEX","@Column|@Entity|@Table"],"file_scopes":["backend/src/main/resources/db/migration/*.sql","backend/src/main/kotlin/**/domain/*.kt","backend/src/main/kotlin/**/dto/*.kt","backend/src/main/java/**/domain/*.java","backend/src/main/java/**/dto/*.java","be/src/main/resources/db/migration/*.sql","be/src/main/kotlin/**/domain/*.kt","be/src/main/kotlin/**/dto/*.kt","be/src/main/java/**/domain/*.java","be/src/main/java/**/dto/*.java","frontend/lib/**/entities/*.dart","frontend/lib/**/models/*.dart","fe/lib/**/entities/*.dart","fe/lib/**/models/*.dart"],"cross_check":"마이그레이션 → 엔티티 → DTO → FE 모델 → FE 엔티티 전체 체인 업데이트","known_pitfalls":["기존 CHECK 제약조건 무시","closingDay/settlementDay 등 nullable 필드 미처리"]}},"lessons":[{"date":"2026-04-02","project":"budget-book","classification":["amount_calculation"],"symptom":"금액 변경 시 1곳만 수정, 나머지 19곳 누락","root_cause":"금액 표시 위치가 20곳인데 한 곳만 수정","missed_locations":["StatisticsService","PaymentMethodStatisticsService","ReportService","BudgetService","MonthSummaryBar","PeriodSummary"],"prevention":"금액 관련 변경 시 grep 'totalExpense|totalIncome|sumOf' 전수 조사"},{"date":"2026-04-14","project":"budget-book","classification":["amount_calculation"],"symptom":"이체(Transfer) 금액이 카드 결제 현황에 미포함","root_cause":"PaymentMethodService.buildMonthByTransactionDate가 Transaction만 조회, Transfer 미포함","missed_locations":["PaymentMethodService.getCardSettlementSummary"],"prevention":"결제수단별 총 지출 = 거래 + 이체 출금. transferRepository 조회 필수"},{"date":"2026-04-14","project":"budget-book","classification":["amount_calculation"],"symptom":"FE MonthSummaryBar에서 이체 이중 합산","root_cause":"BE getMonthlySummary가 이미 Transfer 포함하는데 FE에서 transferOut을 다시 더함","missed_locations":["transaction_list_page.dart MonthSummaryBar 호출"],"prevention":"BE 합계 사용 시 FE에서 Transfer를 추가로 더하지 않음"},{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"dateFrom/dateTo 필터가 거래 API에 전달되지 않음","root_cause":"BLoC 이벤트에 dateFrom/dateTo 있으나 Repository 호출에서 누락","missed_locations":["transaction_bloc.dart","transaction_repository_impl.dart","transaction_remote_datasource.dart"],"prevention":"필터 추가 시 Event→BLoC→Repo→DataSource→API 전체 체인 확인"},{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-14","project":"budget-book","classification":["navigation_state"],"symptom":"예산 3월→카드 선택→4월 거래 표시","root_cause":"결제수단 페이지에서 거래이력 이동 시 year/month 미전달. BE API가 YearMonth.now() 하드코딩","missed_locations":["payment_method_page.dart","PaymentMethodController.kt","PaymentMethodService.kt"],"prevention":"화면 이동 시 현재 보고 있는 월/상태를 목적지에 전달. BE API에 하드코딩 제거"},{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스가 존재했지만 기획서 작성 시 실행되지 않음","root_cause":"하네스 도구를 만들었으나 AI Command Protocol(CLAUDE.md)에 강제 단계로 삽입하지 않음","missed_locations":["CLAUDE.md Step 1~2 사이","MEMORY.md"],"prevention":"도구 생성 시 반드시 CLAUDE.md 프로토콜 + MEMORY.md에 동시 연결. 도구 존재 ≠ 프로세스 강제"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation"],"symptom":"카드 결제 대상에 이체(Transfer) 금액 미포함 — 하네스 STRUCTURAL_FIX_REQUIRED 경고 후에도 재발","root_cause":"getSettlementTransactions에서 Transaction만 조회, Transfer 완전 누락. buildMonthBySettlementDate도 Transfer 미포함","missed_locations":["TransactionService.getSettlementTransactions","PaymentMethodService.buildMonthBySettlementDate"],"prevention":"카드 관련 금액 조회 시 항상 Transaction + Transfer 합산. 체크리스트: (1) transactionRepository (2) transferRepository.findBySource (3) 합계에 둘 다 포함"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행","root_cause":"plan-audit.sh Hook은 기획서(_plan.md) 작성 시에만 트리거됨. 기획서 없이 바로 Edit tool 사용하면 우회 가능. PreToolUse(Edit) hook 부재로 CLAUDE.md Step 1/1.5 강제 실패","missed_locations":["PreToolUse Edit hook 없음","CLAUDE.md Step 1 강제 안 됨","사용자가 직접 지적할 때까지 AI가 자체 검증 안 함"],"prevention":"PreToolUse(Edit|Write) hook 추가 — 최근 N분 내에 _plan.md가 작성/수정되지 않았으면 경고. 사용자가 1줄 요청해도 반드시 기획서 작성 후 진행."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}],"tracker":{"navigation_state":{"description":"화면 이동 시 year/month 등 상태 미전달","count":2,"threshold":3,"incidents":[{"date":"2026-04-14","symptom":"예산 3월→카드 선택→4월 거래 표시","missed":["payment_method_page.dart","PaymentMethodService.kt"]},{"date":"2026-04-15","symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","missed":["dashboard_page.dart(3곳)","transaction_detail_page.dart","transaction_form_page.dart"]}],"action":"ESCALATION_WARNING","structural_fix_proposal":"navigation_helpers.dart 중앙 헬퍼 — year/month required 파라미터로 누락 방지","next_occurrence_action":"STRUCTURAL_FIX_REQUIRED"},"amount_calculation":{"description":"금액 합계/집계 한 곳만 수정, 나머지 누락","count":3,"threshold":3,"incidents":[{"date":"2026-04-02","symptom":"금액 변경 시 1곳만 수정, 19곳 누락","missed":["StatisticsService","PaymentMethodStatisticsService","ReportService","BudgetService","MonthSummaryBar","PeriodSummary"]},{"date":"2026-04-14","symptom":"Transfer 금액 카드 결제 현황 미포함","missed":["PaymentMethodService.getCardSettlementSummary"]},{"date":"2026-04-14","symptom":"FE MonthSummaryBar 이체 이중 합산","missed":["transaction_list_page.dart"]}],"action":"STRUCTURAL_FIX_REQUIRED","structural_fix_proposal":"금액 계산 중앙 서비스 — BE 응답이 단일 진실, FE에서 개별 합산 금지"},"meta_process":{"description":"프로세스/도구 생성 시 강제 적용 연결 누락","count":1,"threshold":2,"incidents":[{"date":"2026-04-15","symptom":"하네스 도구 존재했지만 기획서 작성 시 실행되지 않음","missed":["CLAUDE.md Step 1~2","MEMORY.md"]}],"action":"OK","structural_fix_proposal":"도구 생성 체크리스트: (1) CLAUDE.md 프로토콜 삽입 (2) MEMORY.md 참조 추가 (3) Hook 자동 트리거 검토","next_occurrence_action":"STRUCTURAL_FIX_REQUIRED"},"filter_propagation":{"description":"필터 파라미터가 Event→BLoC→Repo→DataSource→API 체인 중 누락","count":3,"threshold":3,"incidents":[{"date":"2026-04-14","symptom":"dateFrom/dateTo 거래 API 미전달","missed":["transaction_bloc.dart","transaction_repository_impl.dart","transaction_remote_datasource.dart"]},{"date":"2026-04-14","symptom":"PeriodSummary 필터 API 미전달","missed":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"]},{"date":"2026-04-15","symptom":"LoadCardSettlementSummary year/month 미전달","missed":["payment_method_bloc.dart"]}],"action":"STRUCTURAL_FIX_REQUIRED","structural_fix_proposal":"필터 체인 체커 스크립트 — Event→BLoC→Repo→DataSource 각 레이어에서 파라미터 존재 여부 자동 검증"}},"audit_history":[],"requests":[{"id":"req-1776416585120-015","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"카드결제가 완료되었습니다. 나오나 거래 내역에는 자동으로 반영되지 않아 새로고침해야하는 문제 존재","tags":["ui_pattern"],"tags_auto":true,"step":"done","risk_level":"OK","created_at":"2026-04-17T18:03:05.120325+09:00","updated_at":"2026-04-20T14:03:36.821924+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장","24fe7f4 chore: 하네스 자동화 — Hook 기반 기획서 검토 + 세션 기록","6cf29b5 feat: 금액 입력 계산기 사칙연산(*, /) 지원"],"tag_files":["frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart"],"keyword_files":[{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/BudgetBookApplication.kt","hits":1},{"file":"frontend/lib/core/router/app_router.dart","hits":1},{"file":"frontend/lib/core/widgets/amount_input_field.dart","hits":1},{"file":"frontend/lib/core/widgets/icon_picker.dart","hits":1},{"file":"frontend/lib/core/utils/couple_mode.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/core/widgets/month_navigator.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"auto","line":"50:  bool _autoExpandedOnce = false;"},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"auto","line":"162:    // Auto-expand the group containing the selected category (once)"},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"auto","line":"163:    if (!_autoExpandedOnce && widget.selectedCategoryId != null) {"},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"reload","line":"84:          // When a category is created/deleted, reload groups to get updated lists"},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"update","line":"84:          // When a category is created/deleted, reload groups to get updated lists"},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","term":"update","line":"711:      getIt<CategoryBloc>().add(UpdateCategory("},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"16:class CardAutoSettlementScheduler("},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"33:        log.info(\"Auto-settlement: found {} cards for settlement day {}\", cards.size, dayOfMonth)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"39:                log.info(\"Auto-settlement: skipping duplicate for card {} ({})\", card.id, card.name)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"payment","line":"1:package com.budgetbook.paymentmethod.scheduler"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"payment","line":"3:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"payment","line":"4:import com.budgetbook.paymentmethod.repository.PaymentMethodRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"auto","line":"290:     * Auto-seeds for existing couples that were created before the visibility feature."},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"auto","line":"305:            log.warn(\"Failed to auto-seed private categories for userId={}: {}\", userId, e.message)"},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"update","line":"10:import com.budgetbook.category.dto.UpdateCategoryGroupRequest"},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"update","line":"116:    fun updateCategoryGroup(userId: UUID, groupId: UUID, request: UpdateCategoryGroupRequest): CategoryGroupResponse {"},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"update","line":"163:                    transactionRepository.updateVisibilityByCategoryId("},{"file":"backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","term":"auto","line":"3:import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty"},{"file":"backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","term":"auto","line":"5:import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression"}],"file_count":715,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","backend/src/main/kotlin/com/budgetbook/BudgetBookApplication.kt","frontend/lib/core/router/app_router.dart","frontend/lib/core/widgets/amount_input_field.dart","frontend/lib/core/widgets/icon_picker.dart","frontend/lib/core/utils/couple_mode.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/core/widgets/month_navigator.dart"]},"generated_plan":"# 카드결제가 완료되었습니다. 나오나 거래 내역에는 자동으로 반영되지 않아 새로고침해야하는 문제 존재\n> 2026-04-17 18:03 | budget-book | 위험도: OK\n\n## 1. 증상\n카드결제가 완료되었습니다. 나오나 거래 내역에는 자동으로 반영되지 않아 새로고침해야하는 문제 존재\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/widgets/category_group_selector_sheet.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/BudgetBookApplication.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/router/app_router.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/widgets/category_group_selector_sheet.dart` — 50:  bool _autoExpandedOnce = false;\n  `frontend/lib/core/widgets/category_group_selector_sheet.dart` — 162:    // Auto-expand the group containing the selected category (once)\n  `frontend/lib/core/widgets/category_group_selector_sheet.dart` — 163:    if (!_autoExpandedOnce && widget.selectedCategoryId != null) {\n  `frontend/lib/core/widgets/category_group_selector_sheet.dart` — 84:          // When a category is created/deleted, reload groups to get updated lists\n  `frontend/lib/core/widgets/category_group_selector_sheet.dart` — 711:      getIt<CategoryBloc>().add(UpdateCategory(\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 16:class CardAutoSettlementScheduler(\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 33:        log.info(\"Auto-settlement: found {} cards for settlement day {}\", cards.size, dayOfMonth)\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 39:                log.info(\"Auto-settlement: skipping duplicate for card {} ({})\", card.id, card.name)\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 1:package com.budgetbook.paymentmethod.scheduler\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 3:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 4:import com.budgetbook.paymentmethod.repository.PaymentMethodRepository\n  `backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt` — 290:     * Auto-seeds for existing couples that were created before the visibility feature.\n\n### 최근 커밋\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n- b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)\n- b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/widgets/category_group_selector_sheet.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 35개 | 소스 715개","step_notes":{},"history":[{"step":"request","at":"2026-04-17T18:03:05.120325+09:00","note":"작업 요청 접수: 카드결제가 완료되었습니다. 나오나 거래 내역에는 자동으로 반영되지 않아 새로고침해야하는 문제 존재"},{"step":"audit","at":"2026-04-17T18:03:06.120846+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-17T18:03:07.403170+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-17T18:03:08.403771+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-17T18:03:08.806849+09:00","note":"기획서 자동 생성 완료 (4368자)"},{"step":"approved","at":"2026-04-17T18:03:09.307400+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"dev","at":"2026-04-17T18:03:52.020554+09:00","note":"승인 → 개발"},{"step":"review","at":"2026-04-17T18:04:04.218829+09:00","note":"개발 → 검증"},{"step":"done","at":"2026-04-17T18:04:32.094935+09:00","note":"검증 → 완료"}],"error":null,"notes":"검증 → 완료","phase":"Phase 20-I: 카드결제 UX"},{"id":"req-1776611936458-001","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"월 이동 시 거래내역 필터(dateFrom/To, keyword, amount 등) drop 방지 + 카테고리 필터 바닥시트 크래시 수정","tags":["navigation_state","filter_propagation","ui_pattern"],"tags_auto":false,"step":"done","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T00:18:56.458367+09:00","updated_at":"2026-04-20T14:03:36.854347+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"navigation_state","risk":"WARNING","pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"],"grep_count":2,"lesson_count":3,"tracker_count":2,"tracker_threshold":3},{"tag":"filter_propagation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"],"grep_count":3,"lesson_count":3,"tracker_count":3,"tracker_threshold":3},{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."},{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/login_page.dart","frontend/lib/features/home/presentation/pages/dashboard_page.dart","backend/src/test/kotlin/com/budgetbook/category/controller/CategoryControllerTest.kt","frontend/lib/core/widgets/item_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/auth_callback_page.dart","frontend/lib/app.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/features/home/presentation/widgets/monthly_trend_card.dart","frontend/test/features/auth/presentation/pages/login_page_test.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","frontend/lib/features/budget/presentation/widgets/budget_suggestion_card.dart","frontend/test/features/onboarding/presentation/pages/onboarding_page_test.dart","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart"],"keyword_files":[{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":3},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":2},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":2},{"file":"frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","hits":2},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"2:import 'package:budget_book/core/models/unified_filter_state.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"4:import 'package:budget_book/core/widgets/filters/category_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"2:import 'package:budget_book/core/models/unified_filter_state.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"4:import 'package:budget_book/core/widgets/filters/category_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"drop","line":"304:                  // Payment method dropdown"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"drop","line":"313:                  // Pocket dropdown"},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"Filter","line":"13:/// Shows a bottom sheet with transactions filtered by categoryId for a budget item."},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"Filter","line":"151:                final transactions = state.filteredTransactions;"},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"Filter","line":"177:                final grouped = state.filteredGroupedByDate;"},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"filter","line":"13:/// Shows a bottom sheet with transactions filtered by categoryId for a budget item."},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"filter","line":"151:                final transactions = state.filteredTransactions;"},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","term":"filter","line":"177:                final grouped = state.filteredGroupedByDate;"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"Filter","line":"40:        private val VALID_VISIBILITY_FILTERS = setOf(\"ALL\", \"SHARED\", \"PRIVATE\")"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"Filter","line":"45:        if (upper !in VALID_VISIBILITY_FILTERS) {"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"Filter","line":"46:            throw BusinessException(\"VALIDATION_ERROR\", \"Invalid visibility filter: $visibility. Must be one of: ALL, SHARED, PRIVATE\")"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"filter","line":"40:        private val VALID_VISIBILITY_FILTERS = setOf(\"ALL\", \"SHARED\", \"PRIVATE\")"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"filter","line":"45:        if (upper !in VALID_VISIBILITY_FILTERS) {"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"filter","line":"46:            throw BusinessException(\"VALIDATION_ERROR\", \"Invalid visibility filter: $visibility. Must be one of: ALL, SHARED, PRIVATE\")"}],"file_count":717,"related_files":["frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/core/bloc/month_sync_handler.dart","backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt"]},"generated_plan":"# 월 이동 시 거래내역 필터(dateFrom/To, keyword, amount 등) drop 방지 + 카테고리 필터 바닥시트 크래시 수정\n> 2026-04-20 00:19 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n월 이동 시 거래내역 필터(dateFrom/To, keyword, amount 등) drop 방지 + 카테고리 필터 바닥시트 크래시 수정\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 3회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 2회 매칭\n- **`frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/bloc/month_sync_handler.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 2:import 'package:budget_book/core/models/unified_filter_state.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 4:import 'package:budget_book/core/widgets/filters/category_filter.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 304:                  // Payment method dropdown\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 313:                  // Pocket dropdown\n  `frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart` — 13:/// Shows a bottom sheet with transactions filtered by categoryId for a budget item.\n  `frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart` — 151:                final transactions = state.filteredTransactions;\n  `frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart` — 177:                final grouped = state.filteredGroupedByDate;\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 40:        private val VALID_VISIBILITY_FILTERS = setOf(\"ALL\", \"SHARED\", \"PRIVATE\")\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 45:        if (upper !in VALID_VISIBILITY_FILTERS) {\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 46:            throw BusinessException(\"VALIDATION_ERROR\", \"Invalid visibility filter: $visibility. Must be one of: ALL, SHARED, PRIVATE\")\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**navigation_state**: 재발 2/3 ⚠ WARNING\n  - ⚠ year/month를 전달하지 않아 항상 현재 달로 로드\n  - ⚠ categoryId/paymentMethodId만 전달하고 기간 정보 누락\n  - ⚠ BE API가 YearMonth.now() 하드코딩\n**filter_propagation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ BLoC 이벤트에는 있으나 Repository 호출에서 누락\n  - ⚠ DataSource에서 API 쿼리 파라미터에 미포함\n  - ⚠ 클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n- [2026-04-14] PeriodSummary 필터(카테고리/결제수단)가 API에 미전달\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/widgets/filters/unified_filter_bar.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` 확인 및 수정\n- [ ] `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 navigation_state, filter_propagation, ui_pattern | 관련 파일 35개 | 소스 717개","step_notes":{"review":[{"type":"artifact","content":"PR: https://github.com/AIVA-SaaS/budget-book/pull/103 (merged)","at":"2026-04-20T13:46:33.446762+09:00"}]},"history":[{"step":"request","at":"2026-04-20T00:18:56.458367+09:00","note":"작업 요청 접수: 월 이동 시 거래내역 필터(dateFrom/To, keyword, amount 등) drop 방지 + 카테고리 필터 바닥시트 크래시 수정"},{"step":"audit","at":"2026-04-20T00:18:57.464531+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: navigation_state, filter_propagation, ui_pattern)"},{"step":"audit","at":"2026-04-20T00:18:58.912119+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T00:19:00.160677+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T00:19:00.197263+09:00","note":"기획서 자동 생성 완료 (4948자)"},{"step":"approved","at":"2026-04-20T00:19:00.752188+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"done","at":"2026-04-20T13:46:33.359240+09:00","note":"PR #103 머지 + GitHub Actions 자동 배포 완료 (main: ef62759)"},{"step":"review","at":"2026-04-20T13:46:33.446762+09:00","note":"[artifact] PR: https://github.com/AIVA-SaaS/budget-book/pull/103 (merged)"}],"error":null,"notes":"PR #103 머지 + GitHub Actions 자동 배포 완료 (main: ef62759)","phase":"Filter 구조 개선"},{"id":"req-1776611936487-002","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"UnifiedPeriodCubit 도입 — dateRange/week 포함 중앙 period 상태. StatisticsBloc/ReportBloc 까지 패턴 확장, CODEMAP 문서","tags":["navigation_state","filter_propagation"],"tags_auto":false,"step":"done","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T00:18:56.487126+09:00","updated_at":"2026-04-20T14:03:36.897375+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"navigation_state","risk":"WARNING","pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"],"grep_count":2,"lesson_count":3,"tracker_count":2,"tracker_threshold":3},{"tag":"filter_propagation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"],"grep_count":3,"lesson_count":3,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."},{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/login_page.dart","frontend/lib/features/home/presentation/pages/dashboard_page.dart","backend/src/test/kotlin/com/budgetbook/category/controller/CategoryControllerTest.kt","frontend/lib/core/widgets/item_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/auth_callback_page.dart","frontend/lib/app.dart","frontend/lib/features/home/presentation/widgets/monthly_trend_card.dart","frontend/test/features/auth/presentation/pages/login_page_test.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/budget/presentation/widgets/budget_suggestion_card.dart","frontend/test/features/onboarding/presentation/pages/onboarding_page_test.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/test/kotlin/com/budgetbook/category/service/CategoryServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/main/kotlin/com/budgetbook/budget/controller/BudgetController.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionExportServiceTest.kt","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt"],"keyword_files":[{"file":"frontend/lib/core/di/injection.dart","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":2},{"file":"frontend/lib/core/router/app_router.dart","hits":2},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","hits":2},{"file":"frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart","hits":2},{"file":"frontend/lib/features/statistics/presentation/pages/statistics_page.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/report/dto/ReportDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/report/controller/ReportController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/recurring/domain/RecurringTransaction.kt","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/models/unified_filter_state.dart","hits":1},{"file":"frontend/lib/features/statistics/presentation/bloc/statistics_state.dart","hits":1},{"file":"frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","hits":1},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/di/injection.dart","term":"week","line":"37:import 'package:budget_book/features/weekly_budget/data/datasources/weekly_budget_remote_datasource.dart';"},{"file":"frontend/lib/core/di/injection.dart","term":"week","line":"38:import 'package:budget_book/features/weekly_budget/data/repositories/weekly_budget_repository_impl.dart';"},{"file":"frontend/lib/core/di/injection.dart","term":"week","line":"39:import 'package:budget_book/features/weekly_budget/domain/repositories/weekly_budget_repository.dart';"},{"file":"frontend/lib/core/di/injection.dart","term":"StatisticsBloc","line":"209:  getIt.registerLazySingleton<StatisticsBloc>("},{"file":"frontend/lib/core/di/injection.dart","term":"StatisticsBloc","line":"210:    () => StatisticsBloc("},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"week","line":"430:            val effectiveAmount = if (budget.budgetPeriod == BudgetPeriod.WEEKLY) {"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"week","line":"431:                val weeklyAmt = budget.weeklyAmount ?: (budget.amount * 7 / ym.lengthOfMonth())"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"week","line":"432:                weeklyAmt * ym.lengthOfMonth().toLong() / 7"},{"file":"frontend/lib/core/router/app_router.dart","term":"week","line":"42:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_bloc.dart';"},{"file":"frontend/lib/core/router/app_router.dart","term":"week","line":"43:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_event.dart';"},{"file":"frontend/lib/core/router/app_router.dart","term":"week","line":"44:import 'package:budget_book/features/weekly_budget/presentation/pages/weekly_budget_page.dart';"},{"file":"frontend/lib/core/router/app_router.dart","term":"StatisticsBloc","line":"335:                return BlocProvider<StatisticsBloc>("},{"file":"frontend/lib/core/router/app_router.dart","term":"StatisticsBloc","line":"336:                  create: (_) => getIt<StatisticsBloc>()"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"week","line":"23:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_bloc.dart';"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"week","line":"24:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_event.dart';"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"week","line":"107:    // Weekly budget overview + current week"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"StatisticsBloc","line":"101:      final statBloc = getIt<StatisticsBloc>();"},{"file":"frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart","term":"StatisticsBloc","line":"9:class StatisticsBloc extends Bloc<StatisticsEvent, StatisticsState> {"},{"file":"frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart","term":"StatisticsBloc","line":"12:  StatisticsBloc({required this.statisticsRepository})"}],"file_count":717,"related_files":["frontend/lib/core/di/injection.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/router/app_router.dart","frontend/lib/core/bloc/month_sync_handler.dart","frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/main/kotlin/com/budgetbook/report/dto/ReportDtos.kt","backend/src/main/kotlin/com/budgetbook/report/controller/ReportController.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/recurring/domain/RecurringTransaction.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/models/unified_filter_state.dart","frontend/lib/features/statistics/presentation/bloc/statistics_state.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart"]},"generated_plan":"# UnifiedPeriodCubit 도입 — dateRange/week 포함 중앙 period 상태. StatisticsBloc/ReportBloc 까지 패턴 확장, CODEMAP 문서\n> 2026-04-20 00:19 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\nUnifiedPeriodCubit 도입 — dateRange/week 포함 중앙 period 상태. StatisticsBloc/ReportBloc 까지 패턴 확장, CODEMAP 문서\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/di/injection.dart`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 2회 매칭\n- **`frontend/lib/core/router/app_router.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/bloc/month_sync_handler.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/statistics/presentation/pages/statistics_page.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/report/dto/ReportDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/report/controller/ReportController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/recurring/domain/RecurringTransaction.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/di/injection.dart` — 37:import 'package:budget_book/features/weekly_budget/data/datasources/weekly_budget_remote_datasource.dart';\n  `frontend/lib/core/di/injection.dart` — 38:import 'package:budget_book/features/weekly_budget/data/repositories/weekly_budget_repository_impl.dart';\n  `frontend/lib/core/di/injection.dart` — 39:import 'package:budget_book/features/weekly_budget/domain/repositories/weekly_budget_repository.dart';\n  `frontend/lib/core/di/injection.dart` — 209:  getIt.registerLazySingleton<StatisticsBloc>(\n  `frontend/lib/core/di/injection.dart` — 210:    () => StatisticsBloc(\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 430:            val effectiveAmount = if (budget.budgetPeriod == BudgetPeriod.WEEKLY) {\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 431:                val weeklyAmt = budget.weeklyAmount ?: (budget.amount * 7 / ym.lengthOfMonth())\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 432:                weeklyAmt * ym.lengthOfMonth().toLong() / 7\n  `frontend/lib/core/router/app_router.dart` — 42:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_bloc.dart';\n  `frontend/lib/core/router/app_router.dart` — 43:import 'package:budget_book/features/weekly_budget/presentation/bloc/weekly_budget_event.dart';\n  `frontend/lib/core/router/app_router.dart` — 44:import 'package:budget_book/features/weekly_budget/presentation/pages/weekly_budget_page.dart';\n  `frontend/lib/core/router/app_router.dart` — 335:                return BlocProvider<StatisticsBloc>(\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**navigation_state**: 재발 2/3 ⚠ WARNING\n  - ⚠ year/month를 전달하지 않아 항상 현재 달로 로드\n  - ⚠ categoryId/paymentMethodId만 전달하고 기간 정보 누락\n  - ⚠ BE API가 YearMonth.now() 하드코딩\n**filter_propagation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ BLoC 이벤트에는 있으나 Repository 호출에서 누락\n  - ⚠ DataSource에서 API 쿼리 파라미터에 미포함\n  - ⚠ 클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n- [2026-04-14] PeriodSummary 필터(카테고리/결제수단)가 API에 미전달\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/di/injection.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/router/app_router.dart` 확인 및 수정\n- [ ] `frontend/lib/core/bloc/month_sync_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/features/statistics/presentation/bloc/statistics_bloc.dart` 확인 및 수정\n- [ ] `frontend/lib/features/statistics/presentation/pages/statistics_page.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/report/dto/ReportDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/report/controller/ReportController.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 navigation_state, filter_propagation | 관련 파일 35개 | 소스 717개","step_notes":{"review":[{"type":"artifact","content":"PR: https://github.com/AIVA-SaaS/budget-book/pull/103 (merged)","at":"2026-04-20T13:46:33.725682+09:00"}]},"history":[{"step":"request","at":"2026-04-20T00:18:56.487126+09:00","note":"작업 요청 접수: UnifiedPeriodCubit 도입 — dateRange/week 포함 중앙 period 상태. StatisticsBloc/ReportBloc 까지 패턴 확장, CODEMAP 문서"},{"step":"audit","at":"2026-04-20T00:18:58.014455+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: navigation_state, filter_propagation)"},{"step":"audit","at":"2026-04-20T00:18:59.204258+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T00:19:00.923228+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T00:19:00.924773+09:00","note":"기획서 자동 생성 완료 (4702자)"},{"step":"approved","at":"2026-04-20T00:19:01.606361+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"done","at":"2026-04-20T13:46:33.640051+09:00","note":"fix/period-filter-structural 브랜치에 포함 → PR #103 머지"},{"step":"review","at":"2026-04-20T13:46:33.725682+09:00","note":"[artifact] PR: https://github.com/AIVA-SaaS/budget-book/pull/103 (merged)"}],"error":null,"notes":"fix/period-filter-structural 브랜치에 포함 → PR #103 머지","phase":"Filter 구조 개선"},{"id":"req-1776611937041-003","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"카테고리 선택 목록, 결제수단 목록, 날짜 위치 등 UI 불일치 전수 검수 및 통일","tags":["ui_pattern"],"tags_auto":false,"step":"review","risk_level":"OK","created_at":"2026-04-20T00:18:57.041310+09:00","updated_at":"2026-04-20T14:03:36.929263+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/payment_method_filter.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"56:    @JoinColumn(name = \"payment_method_id\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"23:        GROUP BY tr.destinationPaymentMethod.id"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"23:        GROUP BY tr.destinationPaymentMethod.id"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"payment","line":"54:            sourcePaymentMethodId = request.sourcePaymentMethodId,"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"payment","line":"55:            destinationPaymentMethodId = request.destinationPaymentMethodId,"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"PaymentMethod","line":"54:            sourcePaymentMethodId = request.sourcePaymentMethodId,"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/payment_method_filter.dart"]},"generated_plan":"# 카테고리 선택 목록, 결제수단 목록, 날짜 위치 등 UI 불일치 전수 검수 및 통일\n> 2026-04-20 00:19 | budget-book | 위험도: OK\n\n## 1. 증상\n카테고리 선택 목록, 결제수단 목록, 날짜 위치 등 UI 불일치 전수 검수 및 통일\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 8:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 56:    @JoinColumn(name = \"payment_method_id\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 57:    var paymentMethod: PaymentMethod? = null,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 1:package com.budgetbook.paymentmethod.service\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 9:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 10:import com.budgetbook.paymentmethod.domain.PaymentMethodType\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 23:        GROUP BY tr.destinationPaymentMethod.id\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)\n  `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` — 54:            sourcePaymentMethodId = request.sourcePaymentMethodId,\n  `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` — 55:            destinationPaymentMethodId = request.destinationPaymentMethodId,\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 33개 | 소스 717개","step_notes":{"review":[{"type":"artifact","content":"PR 대기: https://github.com/AIVA-SaaS/budget-book/pull/new/fix/ui-consistency-date-currency","at":"2026-04-20T13:46:33.943760+09:00"}]},"history":[{"step":"request","at":"2026-04-20T00:18:57.041310+09:00","note":"작업 요청 접수: 카테고리 선택 목록, 결제수단 목록, 날짜 위치 등 UI 불일치 전수 검수 및 통일"},{"step":"audit","at":"2026-04-20T00:18:58.042591+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T00:19:00.037391+09:00","note":"코드 분석: 관련 파일 13개, 커밋 10건"},{"step":"plan","at":"2026-04-20T00:19:01.160412+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T00:19:01.161880+09:00","note":"기획서 자동 생성 완료 (4264자)"},{"step":"approved","at":"2026-04-20T00:19:01.676191+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"review","at":"2026-04-20T13:46:33.857944+09:00","note":"PR-A 브랜치 push 완료 — 날짜/금액 포매터 통일 부분 (Critical #1, #3 해결). Critical #2,#4,#5 는 후속 PR 예정"},{"step":"review","at":"2026-04-20T13:46:33.943760+09:00","note":"[artifact] PR 대기: https://github.com/AIVA-SaaS/budget-book/pull/new/fix/ui-consistency-date"}],"error":null,"notes":"PR-A 브랜치 push 완료 — 날짜/금액 포매터 통일 부분 (Critical #1, #3 해결). Critical #2,#4,#5 는 후속 PR 예정","phase":"UI 일관성 통일"},{"id":"req-1776658055997-007","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"거래/이체 등 동일 동작 공통화 구조 전수 검수 + 변경 대응 일관성 확보 분석 — 여러 번 요청했음에도 제대로 동작 안 되는 곳 다수","tags":["ui_pattern","meta_process"],"tags_auto":false,"step":"review","risk_level":"WARNING","created_at":"2026-04-20T13:07:35.997550+09:00","updated_at":"2026-04-20T14:03:36.993248+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"meta_process","risk":"WARNING","pitfalls":["도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음","메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름"],"grep_count":3,"lesson_count":2,"tracker_count":1,"tracker_threshold":2}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스가 존재했지만 기획서 작성 시 실행되지 않음","root_cause":"하네스 도구를 만들었으나 AI Command Protocol(CLAUDE.md)에 강제 단계로 삽입하지 않음","missed_locations":["CLAUDE.md Step 1~2 사이","MEMORY.md"],"prevention":"도구 생성 시 반드시 CLAUDE.md 프로토콜 + MEMORY.md에 동시 연결. 도구 존재 ≠ 프로세스 강제"},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행","root_cause":"plan-audit.sh Hook은 기획서(_plan.md) 작성 시에만 트리거됨. 기획서 없이 바로 Edit tool 사용하면 우회 가능. PreToolUse(Edit) hook 부재로 CLAUDE.md Step 1/1.5 강제 실패","missed_locations":["PreToolUse Edit hook 없음","CLAUDE.md Step 1 강제 안 됨","사용자가 직접 지적할 때까지 AI가 자체 검증 안 함"],"prevention":"PreToolUse(Edit|Write) hook 추가 — 최근 N분 내에 _plan.md가 작성/수정되지 않았으면 경고. 사용자가 1줄 요청해도 반드시 기획서 작성 후 진행."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1},{"file":"frontend/lib/core/utils/date_helpers.dart","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_list_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transfer","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"22:import com.budgetbook.transfer.repository.TransferRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"34:    private val transferRepository: TransferRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"Transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"1:package com.budgetbook.transfer.dto"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"16:data class CreateTransferRequest("}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","frontend/lib/core/utils/date_helpers.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt"]},"generated_plan":"# 거래/이체 등 동일 동작 공통화 구조 전수 검수 + 변경 대응 일관성 확보 분석 — 여러 번 요청했음에도 제대로 동작 안 되는 곳 다수\n> 2026-04-20 13:07 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\n거래/이체 등 동일 동작 공통화 구조 전수 검수 + 변경 대응 일관성 확보 분석 — 여러 번 요청했음에도 제대로 동작 안 되는 곳 다수\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/date_helpers.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 1:package com.budgetbook.transaction.domain\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 23:@Table(name = \"transactions\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 24:class Transaction(\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨.\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 21:import com.budgetbook.transaction.repository.TransactionRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 24:import org.springframework.transaction.annotation.Transactional\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 33:    private val transactionRepository: TransactionRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 22:import com.budgetbook.transfer.repository.TransferRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 34:    private val transferRepository: TransferRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 58:    val transactionIds: List<UUID> = emptyList()\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 1:package com.budgetbook.transfer.dto\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**meta_process**: 재발 1/2 ⚠ WARNING\n  - ⚠ 도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음\n  - ⚠ 메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 하네스가 존재했지만 기획서 작성 시 실행되지 않음\n- [2026-04-15] 하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/date_helpers.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, meta_process | 관련 파일 35개 | 소스 717개","step_notes":{"review":[{"type":"artifact","content":"분석 리포트: 공통화 실패 10 영역 / 거래→이체 Base+Variant 설계 / 재발 방지 자동화 / PR 시리즈 순서","at":"2026-04-20T13:46:34.114414+09:00"},{"type":"artifact","content":"PR-1: https://github.com/AIVA-SaaS/budget-book/pull/new/refactor/record-base-pr1","at":"2026-04-20T13:52:06.534489+09:00"}]},"history":[{"step":"request","at":"2026-04-20T13:07:35.997550+09:00","note":"작업 요청 접수: 거래/이체 등 동일 동작 공통화 구조 전수 검수 + 변경 대응 일관성 확보 분석 — 여러 번 요청했음에도 제대로 동작 안 되는 곳 다수"},{"step":"audit","at":"2026-04-20T13:07:37.002288+09:00","note":"Audit Preview: WARNING (태그: ui_pattern, meta_process)"},{"step":"audit","at":"2026-04-20T13:07:38.269855+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:07:39.273981+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:07:39.278293+09:00","note":"기획서 자동 생성 완료 (4537자)"},{"step":"approved","at":"2026-04-20T13:07:40.065409+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"plan","at":"2026-04-20T13:46:34.027005+09:00","note":"탐색 에이전트 분석 완료 — RecordBase 추상화 + AmountDateMemoSection 공통화 + 10-PR 시리즈 계획. STRUCTURAL_FIX_REQUIRED 게이트로 기획서 작성 대기"},{"step":"review","at":"2026-04-20T13:46:34.114414+09:00","note":"[artifact] 분석 리포트: 공통화 실패 10 영역 / 거래→이체 Base+Variant 설계 / 재발 방지 자동화 / PR 시리즈 순서"},{"step":"review","at":"2026-04-20T13:52:06.454290+09:00","note":"PR-1 (RecordBase) 완료 — branch refactor/record-base-pr1 push. 전체 10-PR 시리즈 중 첫 번째. docs/CODEMAPS/COMMON_REFACTOR.md 에 로드맵."},{"step":"review","at":"2026-04-20T13:52:06.534489+09:00","note":"[artifact] PR-1: https://github.com/AIVA-SaaS/budget-book/pull/new/refactor/record-base-pr1"}],"error":null,"notes":"PR-1 (RecordBase) 완료 — branch refactor/record-base-pr1 push. 전체 10-PR 시리즈 중 첫 번째. docs/CODEMAPS/COMMON_REFACTOR.md 에 로드맵.","phase":"공통화 Base+Variant"},{"id":"req-1776660058597-008","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"생활비 & 장 다른 항목인데 같은 금액 표시. 상위 총 예산 금액 vs 각 예산 사용 금액 불일치","tags":["ui_pattern","amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:40:58.597266+09:00","updated_at":"2026-04-20T14:03:37.041652+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","hits":1},{"file":"frontend/lib/core/utils/currency_formatter.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/amount_range_filter.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/amount_input_field.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_form_page.dart","hits":1},{"file":"frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/widgets/pocket_form_sheet.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/widgets/pocket_transfer_form_sheet.dart","hits":1},{"file":"frontend/lib/features/recurring/presentation/pages/recurring_form_page.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"56:            amountMin = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"57:            amountMax = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"85:            val amount = tx.amount.toString()"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"56:            amountMin = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"57:            amountMax = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"85:            val amount = tx.amount.toString()"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"81:            if (prevAmount <= 0) continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"162:        var weekdayTotal = 0L"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"164:        var weekendTotal = 0L"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"180:                weekendTotal += expense"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"81:            if (prevAmount <= 0) continue"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"12:  static String format(num amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"13:    return _numberFormat.format(amount);"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"17:  static String formatWithSign(int amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"amount","line":"12:  static String format(num amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"amount","line":"13:    return _numberFormat.format(amount);"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","frontend/lib/core/utils/currency_formatter.dart","frontend/lib/core/widgets/filters/amount_range_filter.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/amount_input_field.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/features/budget/presentation/pages/budget_form_page.dart","frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","frontend/lib/features/pocket/presentation/widgets/pocket_form_sheet.dart","frontend/lib/features/pocket/presentation/widgets/pocket_transfer_form_sheet.dart","frontend/lib/features/recurring/presentation/pages/recurring_form_page.dart"]},"generated_plan":"# 생활비 & 장 다른 항목인데 같은 금액 표시. 상위 총 예산 금액 vs 각 예산 사용 금액 불일치\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n생활비 & 장 다른 항목인데 같은 금액 표시. 상위 총 예산 금액 vs 각 예산 사용 금액 불일치\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/currency_formatter.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/amount_range_filter.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/amount_input_field.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/budget/presentation/pages/budget_form_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 56:            amountMin = null,\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 57:            amountMax = null,\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 85:            val amount = tx.amount.toString()\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 81:            if (prevAmount <= 0) continue\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 162:        var weekdayTotal = 0L\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 164:        var weekendTotal = 0L\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 180:                weekendTotal += expense\n  `frontend/lib/core/utils/currency_formatter.dart` — 12:  static String format(num amount) {\n  `frontend/lib/core/utils/currency_formatter.dart` — 13:    return _numberFormat.format(amount);\n  `frontend/lib/core/utils/currency_formatter.dart` — 17:  static String formatWithSign(int amount) {\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/currency_formatter.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/amount_range_filter.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/unified_filter_bar.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/amount_input_field.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/balance_adjustment_sheet.dart` 확인 및 수정\n- [ ] `frontend/lib/features/budget/presentation/pages/budget_form_page.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, amount_calculation | 관련 파일 33개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:58.597266+09:00","note":"작업 요청 접수: 생활비 & 장 다른 항목인데 같은 금액 표시. 상위 총 예산 금액 vs 각 예산 사용 금액 불일치"},{"step":"audit","at":"2026-04-20T13:40:59.770066+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: ui_pattern, amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:01.638466+09:00","note":"코드 분석: 관련 파일 13개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:03.668674+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:03.780902+09:00","note":"기획서 자동 생성 완료 (4400자)"},{"step":"approved","at":"2026-04-20T13:41:04.341361+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산 금액 불일치 버그"},{"id":"req-1776660058687-009","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"예산 수정 카테고리 선택에서 상위 그룹 > 하위 형태 표시 안됨","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:40:58.687785+09:00","updated_at":"2026-04-20T14:03:37.073811+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart"]},"generated_plan":"# 예산 수정 카테고리 선택에서 상위 그룹 > 하위 형태 표시 안됨\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n예산 수정 카테고리 선택에서 상위 그룹 > 하위 형태 표시 안됨\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n- `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`\n- `frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt`\n- `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:58.687785+09:00","note":"작업 요청 접수: 예산 수정 카테고리 선택에서 상위 그룹 > 하위 형태 표시 안됨"},{"step":"audit","at":"2026-04-20T13:40:59.810371+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:01.861102+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:03.822722+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:03.829369+09:00","note":"기획서 자동 생성 완료 (1639자)"},{"step":"approved","at":"2026-04-20T13:41:04.349345+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산 관리 UX"},{"id":"req-1776660058816-010","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"구매 목록 계획 설정 시 예산 연결: 주간 예산을 *4주로 표시 → 날짜 선택 기준 해당 주 예산만 표시되어야 함 (첫째주/둘째주 등 개별 표시)","tags":["ui_pattern","amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:40:58.816624+09:00","updated_at":"2026-04-20T14:03:37.105106+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt"]},"generated_plan":"# 구매 목록 계획 설정 시 예산 연결: 주간 예산을 *4주로 표시 → 날짜 선택 기준 해당 주 예산만 표시되어야 함 (첫째주/둘째주 등 개별 표시)\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n구매 목록 계획 설정 시 예산 연결: 주간 예산을 *4주로 표시 → 날짜 선택 기준 해당 주 예산만 표시되어야 함 (첫째주/둘째주 등 개별 표시)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, amount_calculation | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:58.816624+09:00","note":"작업 요청 접수: 구매 목록 계획 설정 시 예산 연결: 주간 예산을 *4주로 표시 → 날짜 선택 기준 해당 주 예산만 표시되어야 함 (첫째주/둘째주 등 개별 표시)"},{"step":"audit","at":"2026-04-20T13:40:59.899413+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: ui_pattern, amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:02.273789+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:03.836221+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:03.842757+09:00","note":"기획서 자동 생성 완료 (2204자)"},{"step":"approved","at":"2026-04-20T13:41:04.357125+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산-계획 연결"},{"id":"req-1776660058907-011","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"주간 예산 반복 (기간 미지정) 기능 추가","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:40:58.907064+09:00","updated_at":"2026-04-20T14:03:37.137029+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart"]},"generated_plan":"# 주간 예산 반복 (기간 미지정) 기능 추가\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n주간 예산 반복 (기간 미지정) 기능 추가\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n- `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`\n- `frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt`\n- `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:58.907064+09:00","note":"작업 요청 접수: 주간 예산 반복 (기간 미지정) 기능 추가"},{"step":"audit","at":"2026-04-20T13:40:59.935567+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:02.497216+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:03.849382+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:03.856020+09:00","note":"기획서 자동 생성 완료 (1615자)"},{"step":"approved","at":"2026-04-20T13:41:04.364856+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산 관리 UX"},{"id":"req-1776660058997-012","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"금액 입력에 +/- 사칙연산 + 지우기 기능","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:40:58.997519+09:00","updated_at":"2026-04-20T14:03:37.168553+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","hits":1},{"file":"frontend/lib/core/utils/currency_formatter.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/amount_range_filter.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/amount_input_field.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_form_page.dart","hits":1},{"file":"frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/widgets/pocket_form_sheet.dart","hits":1},{"file":"frontend/lib/features/pocket/presentation/widgets/pocket_transfer_form_sheet.dart","hits":1},{"file":"frontend/lib/features/recurring/presentation/pages/recurring_form_page.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"56:            amountMin = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"57:            amountMax = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"Amount","line":"85:            val amount = tx.amount.toString()"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"56:            amountMin = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"57:            amountMax = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"amount","line":"85:            val amount = tx.amount.toString()"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"Amount","line":"81:            if (prevAmount <= 0) continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"162:        var weekdayTotal = 0L"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"164:        var weekendTotal = 0L"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"total","line":"180:                weekendTotal += expense"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue"},{"file":"backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","term":"amount","line":"81:            if (prevAmount <= 0) continue"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"12:  static String format(num amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"13:    return _numberFormat.format(amount);"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"Amount","line":"17:  static String formatWithSign(int amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"amount","line":"12:  static String format(num amount) {"},{"file":"frontend/lib/core/utils/currency_formatter.dart","term":"amount","line":"13:    return _numberFormat.format(amount);"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt","frontend/lib/core/utils/currency_formatter.dart","frontend/lib/core/widgets/filters/amount_range_filter.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/amount_input_field.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/features/budget/presentation/pages/budget_form_page.dart","frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","frontend/lib/features/pocket/presentation/widgets/pocket_form_sheet.dart","frontend/lib/features/pocket/presentation/widgets/pocket_transfer_form_sheet.dart","frontend/lib/features/recurring/presentation/pages/recurring_form_page.dart"]},"generated_plan":"# 금액 입력에 +/- 사칙연산 + 지우기 기능\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n금액 입력에 +/- 사칙연산 + 지우기 기능\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/currency_formatter.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/amount_range_filter.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/amount_input_field.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/budget/presentation/pages/budget_form_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 56:            amountMin = null,\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 57:            amountMax = null,\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 85:            val amount = tx.amount.toString()\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 78:        val prevCategoryMap = prevBreakdown.associate { it.category.name to it.amount }\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 80:            val prevAmount = prevCategoryMap[entry.category.name] ?: continue\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 81:            if (prevAmount <= 0) continue\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 162:        var weekdayTotal = 0L\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 164:        var weekendTotal = 0L\n  `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` — 180:                weekendTotal += expense\n  `frontend/lib/core/utils/currency_formatter.dart` — 12:  static String format(num amount) {\n  `frontend/lib/core/utils/currency_formatter.dart` — 13:    return _numberFormat.format(amount);\n  `frontend/lib/core/utils/currency_formatter.dart` — 17:  static String formatWithSign(int amount) {\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/smart/service/SmartAnalysisService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/currency_formatter.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/amount_range_filter.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/unified_filter_bar.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/amount_input_field.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/balance_adjustment_sheet.dart` 확인 및 수정\n- [ ] `frontend/lib/features/budget/presentation/pages/budget_form_page.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 33개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:58.997519+09:00","note":"작업 요청 접수: 금액 입력에 +/- 사칙연산 + 지우기 기능"},{"step":"audit","at":"2026-04-20T13:41:00.543345+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:02.964940+09:00","note":"코드 분석: 관련 파일 13개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:04.188559+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:04.195963+09:00","note":"기획서 자동 생성 완료 (3855자)"},{"step":"approved","at":"2026-04-20T13:41:04.703980+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"입력 UX 고도화"},{"id":"req-1776660059149-013","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"주간 예산에서도 달 이동 가능하게 — MonthSyncHandler 연동","tags":["navigation_state"],"tags_auto":false,"step":"approved","risk_level":"WARNING","created_at":"2026-04-20T13:40:59.149945+09:00","updated_at":"2026-04-20T14:03:37.200073+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"navigation_state","risk":"WARNING","pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"],"grep_count":2,"lesson_count":3,"tracker_count":2,"tracker_threshold":3}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/login_page.dart","frontend/lib/features/home/presentation/pages/dashboard_page.dart","frontend/lib/core/widgets/item_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/auth_callback_page.dart","frontend/lib/app.dart","frontend/lib/features/home/presentation/widgets/monthly_trend_card.dart","frontend/test/features/auth/presentation/pages/login_page_test.dart","frontend/lib/features/budget/presentation/widgets/budget_suggestion_card.dart","frontend/test/features/onboarding/presentation/pages/onboarding_page_test.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/core/router/app_router.dart","frontend/lib/features/home/presentation/widgets/category_breakdown_card.dart","frontend/lib/core/widgets/error_widget.dart","frontend/lib/core/widgets/account_balance_card.dart","frontend/test/features/auth/presentation/pages/auth_callback_page_test.dart","frontend/test/core/router/app_router_test.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"frontend/lib/core/widgets/month_navigator.dart","hits":1},{"file":"frontend/lib/core/bloc/month_cubit.dart","hits":1},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","hits":1},{"file":"frontend/lib/features/home/presentation/pages/dashboard_page.dart","hits":1},{"file":"frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","hits":1},{"file":"frontend/lib/features/report/presentation/pages/report_page.dart","hits":1},{"file":"frontend/lib/features/transaction/domain/entities/transaction_filter.dart","hits":1},{"file":"frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","hits":1},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","hits":1},{"file":"frontend/lib/features/weekly_budget/presentation/pages/weekly_budget_page.dart","hits":1},{"file":"frontend/lib/app.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/widgets/month_navigator.dart","term":"MonthSyncHandler","line":"14:/// 됨 (MonthSyncHandler가 관련 BLoC reload 자동 처리)."},{"file":"frontend/lib/core/widgets/month_navigator.dart","term":"MonthSyncHandler","line":"47:        // 기본 동작: MonthCubit만 업데이트 (MonthSyncHandler가 BLoC reload 처리)"},{"file":"frontend/lib/core/bloc/month_cubit.dart","term":"MonthSyncHandler","line":"10:///   - 반응형 BLoC 연결: MonthSyncHandler 참조"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"MonthSyncHandler","line":"35:class MonthSyncHandler extends StatelessWidget {"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"MonthSyncHandler","line":"38:  const MonthSyncHandler({super.key, required this.child});"},{"file":"frontend/lib/features/home/presentation/pages/dashboard_page.dart","term":"MonthSyncHandler","line":"211:    // MonthCubit만 업데이트 — MonthSyncHandler가 DashboardBloc/BudgetBloc/"},{"file":"frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","term":"MonthSyncHandler","line":"29:    // 이후 월 변경은 MonthSyncHandler가 자동 처리."}],"file_count":717,"related_files":["frontend/lib/core/widgets/month_navigator.dart","frontend/lib/core/bloc/month_cubit.dart","frontend/lib/core/bloc/month_sync_handler.dart","frontend/lib/features/home/presentation/pages/dashboard_page.dart","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/features/transaction/domain/entities/transaction_filter.dart","frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/features/weekly_budget/presentation/pages/weekly_budget_page.dart","frontend/lib/app.dart"]},"generated_plan":"# 주간 예산에서도 달 이동 가능하게 — MonthSyncHandler 연동\n> 2026-04-20 13:41 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\n주간 예산에서도 달 이동 가능하게 — MonthSyncHandler 연동\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/widgets/month_navigator.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/bloc/month_cubit.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/bloc/month_sync_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/home/presentation/pages/dashboard_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/report/presentation/pages/report_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/transaction/domain/entities/transaction_filter.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart`** — 키워드 1회 매칭\n- **`frontend/lib/features/weekly_budget/presentation/pages/weekly_budget_page.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/widgets/month_navigator.dart` — 14:/// 됨 (MonthSyncHandler가 관련 BLoC reload 자동 처리).\n  `frontend/lib/core/widgets/month_navigator.dart` — 47:        // 기본 동작: MonthCubit만 업데이트 (MonthSyncHandler가 BLoC reload 처리)\n  `frontend/lib/core/bloc/month_cubit.dart` — 10:///   - 반응형 BLoC 연결: MonthSyncHandler 참조\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 35:class MonthSyncHandler extends StatelessWidget {\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 38:  const MonthSyncHandler({super.key, required this.child});\n  `frontend/lib/features/home/presentation/pages/dashboard_page.dart` — 211:    // MonthCubit만 업데이트 — MonthSyncHandler가 DashboardBloc/BudgetBloc/\n  `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart` — 29:    // 이후 월 변경은 MonthSyncHandler가 자동 처리.\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**navigation_state**: 재발 2/3 ⚠ WARNING\n  - ⚠ year/month를 전달하지 않아 항상 현재 달로 로드\n  - ⚠ categoryId/paymentMethodId만 전달하고 기간 정보 누락\n  - ⚠ BE API가 YearMonth.now() 하드코딩\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/widgets/month_navigator.dart` 확인 및 수정\n- [ ] `frontend/lib/core/bloc/month_cubit.dart` 확인 및 수정\n- [ ] `frontend/lib/core/bloc/month_sync_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/features/home/presentation/pages/dashboard_page.dart` 확인 및 수정\n- [ ] `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart` 확인 및 수정\n- [ ] `frontend/lib/features/report/presentation/pages/report_page.dart` 확인 및 수정\n- [ ] `frontend/lib/features/transaction/domain/entities/transaction_filter.dart` 확인 및 수정\n- [ ] `frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 navigation_state | 관련 파일 31개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:59.149945+09:00","note":"작업 요청 접수: 주간 예산에서도 달 이동 가능하게 — MonthSyncHandler 연동"},{"step":"audit","at":"2026-04-20T13:41:00.568429+09:00","note":"Audit Preview: WARNING (태그: navigation_state)"},{"step":"audit","at":"2026-04-20T13:41:03.081325+09:00","note":"코드 분석: 관련 파일 11개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:04.203622+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:04.240670+09:00","note":"기획서 자동 생성 완료 (3455자)"},{"step":"approved","at":"2026-04-20T13:41:04.760428+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"주간 예산 확장"},{"id":"req-1776660059269-014","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"예산 계획 — 계획을 어느 예산에 포함시켜 예산 사용 예정이 얼마인지 표시","tags":["ui_pattern","amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:40:59.269211+09:00","updated_at":"2026-04-20T14:03:37.231600+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt"]},"generated_plan":"# 예산 계획 — 계획을 어느 예산에 포함시켜 예산 사용 예정이 얼마인지 표시\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n예산 계획 — 계획을 어느 예산에 포함시켜 예산 사용 예정이 얼마인지 표시\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, amount_calculation | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:59.269211+09:00","note":"작업 요청 접수: 예산 계획 — 계획을 어느 예산에 포함시켜 예산 사용 예정이 얼마인지 표시"},{"step":"audit","at":"2026-04-20T13:41:00.788044+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: ui_pattern, amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:03.239264+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:04.260710+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:04.320462+09:00","note":"기획서 자동 생성 완료 (2124자)"},{"step":"approved","at":"2026-04-20T13:41:04.841810+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산-계획 연결"},{"id":"req-1776660059466-015","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"구매 목록/계획됨 항목을 이미 등록된 거래와 연결 기능","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:40:59.466239+09:00","updated_at":"2026-04-20T14:03:37.264360+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1},{"file":"frontend/lib/core/utils/date_helpers.dart","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_list_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transfer","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"22:import com.budgetbook.transfer.repository.TransferRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"34:    private val transferRepository: TransferRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"Transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"1:package com.budgetbook.transfer.dto"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"16:data class CreateTransferRequest("}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","frontend/lib/core/utils/date_helpers.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt"]},"generated_plan":"# 구매 목록/계획됨 항목을 이미 등록된 거래와 연결 기능\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n구매 목록/계획됨 항목을 이미 등록된 거래와 연결 기능\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/date_helpers.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 1:package com.budgetbook.transaction.domain\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 23:@Table(name = \"transactions\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 24:class Transaction(\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨.\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 21:import com.budgetbook.transaction.repository.TransactionRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 24:import org.springframework.transaction.annotation.Transactional\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 33:    private val transactionRepository: TransactionRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 22:import com.budgetbook.transfer.repository.TransferRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 34:    private val transferRepository: TransferRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 58:    val transactionIds: List<UUID> = emptyList()\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 1:package com.budgetbook.transfer.dto\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/date_helpers.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:59.466239+09:00","note":"작업 요청 접수: 구매 목록/계획됨 항목을 이미 등록된 거래와 연결 기능"},{"step":"audit","at":"2026-04-20T13:41:00.835198+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:03.425348+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:04.431491+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:04.440036+09:00","note":"기획서 자동 생성 완료 (4106자)"},{"step":"approved","at":"2026-04-20T13:41:04.948336+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산-계획 연결"},{"id":"req-1776660059581-016","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"주간별 주차 예산에서 예산 항목 선택 시 해당 항목 거래들만 모아보기","tags":["filter_propagation","ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:40:59.581836+09:00","updated_at":"2026-04-20T14:03:37.296208+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"filter_propagation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"],"grep_count":3,"lesson_count":3,"tracker_count":3,"tracker_threshold":3},{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/category/controller/CategoryControllerTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/main/kotlin/com/budgetbook/budget/controller/BudgetController.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionExportServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt","backend/src/main/kotlin/com/budgetbook/admin/controller/AdminController.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/test/kotlin/com/budgetbook/transaction/controller/TransactionControllerTest.kt","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1},{"file":"frontend/lib/core/utils/date_helpers.dart","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_list_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transfer","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"22:import com.budgetbook.transfer.repository.TransferRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"34:    private val transferRepository: TransferRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"Transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"1:package com.budgetbook.transfer.dto"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"16:data class CreateTransferRequest("}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","frontend/lib/core/utils/date_helpers.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt"]},"generated_plan":"# 주간별 주차 예산에서 예산 항목 선택 시 해당 항목 거래들만 모아보기\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n주간별 주차 예산에서 예산 항목 선택 시 해당 항목 거래들만 모아보기\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/date_helpers.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 1:package com.budgetbook.transaction.domain\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 23:@Table(name = \"transactions\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 24:class Transaction(\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨.\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 21:import com.budgetbook.transaction.repository.TransactionRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 24:import org.springframework.transaction.annotation.Transactional\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 33:    private val transactionRepository: TransactionRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 22:import com.budgetbook.transfer.repository.TransferRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 34:    private val transferRepository: TransferRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 58:    val transactionIds: List<UUID> = emptyList()\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 1:package com.budgetbook.transfer.dto\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**filter_propagation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ BLoC 이벤트에는 있으나 Repository 호출에서 누락\n  - ⚠ DataSource에서 API 쿼리 파라미터에 미포함\n  - ⚠ 클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n## 4. 과거 유사 인시던트\n- [2026-04-14] PeriodSummary 필터(카테고리/결제수단)가 API에 미전달\n- [2026-04-15] LoadCardSettlementSummary year/month 미전달 → 항상 현재 월\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/date_helpers.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 filter_propagation, ui_pattern | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:59.581836+09:00","note":"작업 요청 접수: 주간별 주차 예산에서 예산 항목 선택 시 해당 항목 거래들만 모아보기"},{"step":"audit","at":"2026-04-20T13:41:00.900429+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: filter_propagation, ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:03.661429+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:04.668620+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:04.676936+09:00","note":"기획서 자동 생성 완료 (4566자)"},{"step":"approved","at":"2026-04-20T13:41:05.185315+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"주간 예산 확장"},{"id":"req-1776660059967-017","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"거래 목록 꾹 누를 시 수정/삭제/이동 액션 시트 + 드래그로 날짜 간 자유 이동 UX","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:40:59.967924+09:00","updated_at":"2026-04-20T14:03:37.327942+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1},{"file":"frontend/lib/core/utils/date_helpers.dart","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_list_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transfer","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"22:import com.budgetbook.transfer.repository.TransferRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"34:    private val transferRepository: TransferRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"Transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"1:package com.budgetbook.transfer.dto"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transfer","line":"16:data class CreateTransferRequest("}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","frontend/lib/core/utils/date_helpers.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt"]},"generated_plan":"# 거래 목록 꾹 누를 시 수정/삭제/이동 액션 시트 + 드래그로 날짜 간 자유 이동 UX\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n거래 목록 꾹 누를 시 수정/삭제/이동 액션 시트 + 드래그로 날짜 간 자유 이동 UX\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/date_helpers.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 1:package com.budgetbook.transaction.domain\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 23:@Table(name = \"transactions\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 24:class Transaction(\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨.\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 21:import com.budgetbook.transaction.repository.TransactionRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 24:import org.springframework.transaction.annotation.Transactional\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 33:    private val transactionRepository: TransactionRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 22:import com.budgetbook.transfer.repository.TransferRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 34:    private val transferRepository: TransferRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 58:    val transactionIds: List<UUID> = emptyList()\n  `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` — 1:package com.budgetbook.transfer.dto\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/date_helpers.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:40:59.967924+09:00","note":"작업 요청 접수: 거래 목록 꾹 누를 시 수정/삭제/이동 액션 시트 + 드래그로 날짜 간 자유 이동 UX"},{"step":"audit","at":"2026-04-20T13:41:02.508122+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:04.041930+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:05.049848+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:05.058553+09:00","note":"기획서 자동 생성 완료 (4142자)"},{"step":"approved","at":"2026-04-20T13:41:05.567316+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"거래 조작 UX 고도화"},{"id":"req-1776660060057-018","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"주간 예산 일할 계산 — 월 경계 1원 차이 round 처리 (소수점 round 후 주 예산 - 로 일할 정확히 맞게)","tags":["amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:41:00.057317+09:00","updated_at":"2026-04-20T14:03:37.361608+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","backend/src/test/kotlin/com/budgetbook/transaction/controller/TransactionControllerTest.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","backend/src/test/kotlin/com/budgetbook/report/controller/ReportControllerTest.kt","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklyBudgetServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/PocketTransferServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsServiceTest.kt","frontend/lib/features/statistics/data/models/payment_method_statistics_model.dart","backend/src/test/kotlin/com/budgetbook/pocket/service/MoneyPocketServiceTest.kt"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/budget/service/BudgetService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/budget/service/WeeklyBudgetService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt","hits":1},{"file":"frontend/lib/core/network/auth_interceptor.dart","hits":1},{"file":"frontend/lib/core/utils/dialog_helpers.dart","hits":1},{"file":"frontend/lib/core/widgets/announcement_banner.dart","hits":1},{"file":"frontend/lib/core/widgets/calculator_amount_field.dart","hits":1},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","term":"round","line":"92:                    Math.round(stats.totalSpending.toDouble() / grandTotal * 1000) / 10.0"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"round","line":"188:                    Math.round(entry.amount.toDouble() / totalAmount * 1000) / 10.0"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"round","line":"310:                                Math.round(entry.amount.toDouble() / total * 1000) / 10.0"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"round","line":"357:                            Math.round(entry.amount.toDouble() / total * 1000) / 10.0"},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt","term":"round","line":"42:        // Validate total ratio equals 100 (with 0.01 tolerance for floating-point rounding)"},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","term":"round","line":"51:        const val COOKIE_MAX_AGE_SECONDS = 180 // 3 minutes -- enough for OAuth2 round trip"},{"file":"backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","term":"round","line":"6:import org.aspectj.lang.annotation.Around"},{"file":"backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","term":"round","line":"20:    @Around(\"@annotation(rateLimit)\")"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt","backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/budget/service/BudgetService.kt","backend/src/main/kotlin/com/budgetbook/budget/service/WeeklyBudgetService.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt","frontend/lib/core/network/auth_interceptor.dart","frontend/lib/core/utils/dialog_helpers.dart","frontend/lib/core/widgets/announcement_banner.dart","frontend/lib/core/widgets/calculator_amount_field.dart","frontend/lib/core/widgets/category_group_selector_sheet.dart"]},"generated_plan":"# 주간 예산 일할 계산 — 월 경계 1원 차이 round 처리 (소수점 round 후 주 예산 - 로 일할 정확히 맞게)\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n주간 예산 일할 계산 — 월 경계 1원 차이 round 처리 (소수점 round 후 주 예산 - 로 일할 정확히 맞게)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/budget/service/BudgetService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/budget/service/WeeklyBudgetService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt` — 92:                    Math.round(stats.totalSpending.toDouble() / grandTotal * 1000) / 10.0\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 188:                    Math.round(entry.amount.toDouble() / totalAmount * 1000) / 10.0\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 310:                                Math.round(entry.amount.toDouble() / total * 1000) / 10.0\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 357:                            Math.round(entry.amount.toDouble() / total * 1000) / 10.0\n  `backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt` — 42:        // Validate total ratio equals 100 (with 0.01 tolerance for floating-point rounding)\n  `backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt` — 51:        const val COOKIE_MAX_AGE_SECONDS = 180 // 3 minutes -- enough for OAuth2 round trip\n  `backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt` — 6:import org.aspectj.lang.annotation.Around\n  `backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt` — 20:    @Around(\"@annotation(rateLimit)\")\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/pocket/service/DistributionRatioService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/budget/service/BudgetService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/budget/service/WeeklyBudgetService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 amount_calculation | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:00.057317+09:00","note":"작업 요청 접수: 주간 예산 일할 계산 — 월 경계 1원 차이 round 처리 (소수점 round 후 주 예산 - 로 일할 정확히 맞게)"},{"step":"audit","at":"2026-04-20T13:41:02.708598+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:04.180614+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:05.194035+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:05.202197+09:00","note":"기획서 자동 생성 완료 (4453자)"},{"step":"approved","at":"2026-04-20T13:41:05.725273+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"주간 예산 확장"},{"id":"req-1776660064372-019","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"주간 정산 시스템 — 주간 예산별 사용 금액 처리. 카테고리별 표시 + 전체/개별 완료 처리","tags":["ui_pattern","amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:41:04.372928+09:00","updated_at":"2026-04-20T14:03:37.394353+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","backend/src/test/kotlin/com/budgetbook/report/service/ReportServiceTest.kt","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","frontend/lib/features/report/presentation/pages/report_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart"],"keyword_files":[{"file":"frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","hits":2},{"file":"frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart","hits":2},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","hits":2},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/controller/SpendingPlanController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/domain/SpendingPlan.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt","hits":1},{"file":"frontend/lib/core/network/api_interceptor.dart","hits":1},{"file":"frontend/lib/core/network/auth_interceptor.dart","hits":1},{"file":"frontend/lib/core/router/app_router.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"frontend/lib/features/couple/presentation/pages/couple_page.dart","hits":1},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_form_page.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","term":"complete","line":"163:              'completed': '완료',"},{"file":"frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","term":"Amount","line":"140:            options: {'amount': '금액순', 'count': '건수순'},"},{"file":"frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart","term":"complete","line":"3:import 'package:budget_book/core/router/app_router.dart' show markOnboardingCompleted;"},{"file":"frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart","term":"complete","line":"33:  Future<void> _completeOnboarding() async {"},{"file":"frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart","term":"complete","line":"34:    await markOnboardingCompleted();"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"complete","line":"241:                    ? StepState.complete"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"complete","line":"249:                    ? StepState.complete"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"Amount","line":"20:  final _totalAmountController = TextEditingController();"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"Amount","line":"25:  int get _totalAmount =>"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"Amount","line":"26:      int.tryParse(_totalAmountController.text.replaceAll(',', '')) ?? 0;"},{"file":"frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","term":"success","line":"426:    // Pop happens in BlocListener after successful response"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"complete","line":"108:      // Restore focus after reload completes"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"Amount","line":"134:          amountMin: _filterState.amountMin,"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"Amount","line":"135:          amountMax: _filterState.amountMax,"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"Amount","line":"350:                    amountMin: _filterState.amountMin,"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"success","line":"247:              state.operationSuccess != null) {"},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","term":"success","line":"250:                content: Text(state.operationSuccess!),"},{"file":"backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt","term":"complete","line":"196:            \"Recurring transaction processing complete: {} succeeded, {} failed out of {} total\","},{"file":"backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt","term":"Amount","line":"97:            amount = request.amount,"},{"file":"backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt","term":"Amount","line":"127:        request.amount?.let { recurring.amount = it }"}],"file_count":717,"related_files":["frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart","frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart","frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/controller/SpendingPlanController.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/domain/SpendingPlan.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt","backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt","frontend/lib/core/network/api_interceptor.dart","frontend/lib/core/network/auth_interceptor.dart","frontend/lib/core/router/app_router.dart","backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","frontend/lib/features/couple/presentation/pages/couple_page.dart","frontend/lib/features/transaction/presentation/pages/transaction_form_page.dart"]},"generated_plan":"# 주간 정산 시스템 — 주간 예산별 사용 금액 처리. 카테고리별 표시 + 전체/개별 완료 처리\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n주간 정산 시스템 — 주간 예산별 사용 금액 처리. 카테고리별 표시 + 전체/개별 완료 처리\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart`** — 키워드 2회 매칭\n- **`frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/controller/SpendingPlanController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/domain/SpendingPlan.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/spendingplan/service/SpendingPlanService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/network/api_interceptor.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart` — 163:              'completed': '완료',\n  `frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart` — 140:            options: {'amount': '금액순', 'count': '건수순'},\n  `frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart` — 3:import 'package:budget_book/core/router/app_router.dart' show markOnboardingCompleted;\n  `frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart` — 33:  Future<void> _completeOnboarding() async {\n  `frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart` — 34:    await markOnboardingCompleted();\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 241:                    ? StepState.complete\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 249:                    ? StepState.complete\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 20:  final _totalAmountController = TextEditingController();\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 25:  int get _totalAmount =>\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 26:      int.tryParse(_totalAmountController.text.replaceAll(',', '')) ?? 0;\n  `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` — 426:    // Pop happens in BlocListener after successful response\n  `frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart` — 108:      // Restore focus after reload completes\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/features/home/presentation/widgets/widget_settings_sheet.dart` 확인 및 수정\n- [ ] `frontend/lib/features/onboarding/presentation/pages/onboarding_page.dart` 확인 및 수정\n- [ ] `frontend/lib/features/pocket/presentation/pages/distribute_wizard_page.dart` 확인 및 수정\n- [ ] `frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/recurring/service/RecurringTransactionService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/spendingplan/controller/SpendingPlanController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/spendingplan/domain/SpendingPlan.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/spendingplan/dto/SpendingPlanDtos.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, amount_calculation | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.372928+09:00","note":"작업 요청 접수: 주간 정산 시스템 — 주간 예산별 사용 금액 처리. 카테고리별 표시 + 전체/개별 완료 처리"},{"step":"audit","at":"2026-04-20T13:41:05.384338+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: ui_pattern, amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:06.753979+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:07.763738+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:07.791356+09:00","note":"기획서 자동 생성 완료 (4735자)"},{"step":"approved","at":"2026-04-20T13:41:09.012744+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"주간 예산 확장"},{"id":"req-1776660064403-020","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"색상/아이콘 커스터마이징 고도화 (그라데이션 등)","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:41:04.403684+09:00","updated_at":"2026-04-20T14:03:37.426420+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart"]},"generated_plan":"# 색상/아이콘 커스터마이징 고도화 (그라데이션 등)\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n색상/아이콘 커스터마이징 고도화 (그라데이션 등)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n- `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`\n- `frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt`\n- `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.403684+09:00","note":"작업 요청 접수: 색상/아이콘 커스터마이징 고도화 (그라데이션 등)"},{"step":"audit","at":"2026-04-20T13:41:05.416482+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:06.844481+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:07.912526+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:07.923203+09:00","note":"기획서 자동 생성 완료 (1623자)"},{"step":"approved","at":"2026-04-20T13:41:09.056836+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"색상/아이콘 고도화"},{"id":"req-1776660064449-021","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"4월 카드 기준 미결제액과 이전달 사용 총액 불일치","tags":["amount_calculation"],"tags_auto":false,"step":"approved","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:41:04.449034+09:00","updated_at":"2026-04-20T14:03:37.457875+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","backend/src/test/kotlin/com/budgetbook/transaction/controller/TransactionControllerTest.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionServiceTest.kt","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","backend/src/test/kotlin/com/budgetbook/report/controller/ReportControllerTest.kt","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklyBudgetServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/PocketTransferServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsServiceTest.kt","frontend/lib/features/statistics/data/models/payment_method_statistics_model.dart","backend/src/test/kotlin/com/budgetbook/pocket/service/MoneyPocketServiceTest.kt"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":4},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/dto/PaymentMethodDtos.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/payment_method_filter.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"card","line":"11:import com.budgetbook.paymentmethod.dto.CardPendingResponse"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"card","line":"12:import com.budgetbook.paymentmethod.dto.CardSettlementMonth"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"card","line":"13:import com.budgetbook.paymentmethod.dto.CardSettlementSummaryResponse"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Card","line":"11:import com.budgetbook.paymentmethod.dto.CardPendingResponse"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Card","line":"12:import com.budgetbook.paymentmethod.dto.CardSettlementMonth"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Card","line":"13:import com.budgetbook.paymentmethod.dto.CardSettlementSummaryResponse"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"card","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Card","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"56:    @JoinColumn(name = \"payment_method_id\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"card","line":"16:class CardAutoSettlementScheduler("}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/dto/PaymentMethodDtos.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/payment_method_filter.dart"]},"generated_plan":"# 4월 카드 기준 미결제액과 이전달 사용 총액 불일치\n> 2026-04-20 13:41 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n4월 카드 기준 미결제액과 이전달 사용 총액 불일치\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 4회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/dto/PaymentMethodDtos.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 2회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 11:import com.budgetbook.paymentmethod.dto.CardPendingResponse\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 12:import com.budgetbook.paymentmethod.dto.CardSettlementMonth\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 13:import com.budgetbook.paymentmethod.dto.CardSettlementSummaryResponse\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 1:package com.budgetbook.paymentmethod.service\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 9:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 10:import com.budgetbook.paymentmethod.domain.PaymentMethodType\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨.\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 8:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 56:    @JoinColumn(name = \"payment_method_id\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 57:    var paymentMethod: PaymentMethod? = null,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 16:class CardAutoSettlementScheduler(\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/dto/PaymentMethodDtos.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 amount_calculation | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.449034+09:00","note":"작업 요청 접수: 4월 카드 기준 미결제액과 이전달 사용 총액 불일치"},{"step":"audit","at":"2026-04-20T13:41:05.461484+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: amount_calculation)"},{"step":"audit","at":"2026-04-20T13:41:07.183036+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:08.192706+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:08.204169+09:00","note":"기획서 자동 생성 완료 (4647자)"},{"step":"approved","at":"2026-04-20T13:41:09.396396+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"예산 금액 불일치 버그"},{"id":"req-1776660064481-022","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"카테고리 하위 카테고리 추가 불가 (미분류 > 전체 불가)","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:41:04.481480+09:00","updated_at":"2026-04-20T14:03:37.489552+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[],"keyword_matches":[],"file_count":717,"related_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart"]},"generated_plan":"# 카테고리 하위 카테고리 추가 불가 (미분류 > 전체 불가)\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n카테고리 하위 카테고리 추가 불가 (미분류 > 전체 불가)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- `frontend/lib/core/widgets/category_group_selector_sheet.dart`\n- `frontend/lib/features/statistics/presentation/pages/statistics_page.dart`\n- `frontend/lib/core/widgets/filters/unified_filter_bar.dart`\n- `frontend/lib/features/report/presentation/pages/report_page.dart`\n- `frontend/lib/core/widgets/filters/category_filter.dart`\n- `backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt`\n- `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`\n- `frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart`\n- `backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt`\n- `frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart`\n\n\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 20개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.481480+09:00","note":"작업 요청 접수: 카테고리 하위 카테고리 추가 불가 (미분류 > 전체 불가)"},{"step":"audit","at":"2026-04-20T13:41:05.511782+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:07.274144+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:08.285582+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:09.001712+09:00","note":"기획서 자동 생성 완료 (1633자)"},{"step":"approved","at":"2026-04-20T13:41:09.512732+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"카테고리 관리 버그"},{"id":"req-1776660064532-023","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"카테고리/결제수단 (+ 그외) 입력부에서 추가/삭제는 되는데 수정까지 가능하게","tags":["ui_pattern"],"tags_auto":false,"step":"approved","risk_level":"OK","created_at":"2026-04-20T13:41:04.532609+09:00","updated_at":"2026-04-20T14:03:37.520628+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/core/widgets/filters/category_filter.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","frontend/lib/features/transaction/presentation/widgets/month_summary_bar.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/core/widgets/empty_state_widget.dart","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/payment_method_filter.dart","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"56:    @JoinColumn(name = \"payment_method_id\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"payment","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"8:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"PaymentMethod","line":"57:    var paymentMethod: PaymentMethod? = null,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"payment","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"1:package com.budgetbook.paymentmethod.service"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"9:import com.budgetbook.paymentmethod.domain.PaymentMethod"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"PaymentMethod","line":"10:import com.budgetbook.paymentmethod.domain.PaymentMethodType"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"23:        GROUP BY tr.destinationPaymentMethod.id"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"payment","line":"28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"23:        GROUP BY tr.destinationPaymentMethod.id"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","term":"PaymentMethod","line":"28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"payment","line":"54:            sourcePaymentMethodId = request.sourcePaymentMethodId,"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"payment","line":"55:            destinationPaymentMethodId = request.destinationPaymentMethodId,"},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","term":"PaymentMethod","line":"54:            sourcePaymentMethodId = request.sourcePaymentMethodId,"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/payment_method_filter.dart"]},"generated_plan":"# 카테고리/결제수단 (+ 그외) 입력부에서 추가/삭제는 되는데 수정까지 가능하게\n> 2026-04-20 13:41 | budget-book | 위험도: OK\n\n## 1. 증상\n카테고리/결제수단 (+ 그외) 입력부에서 추가/삭제는 되는데 수정까지 가능하게\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 8:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 56:    @JoinColumn(name = \"payment_method_id\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 57:    var paymentMethod: PaymentMethod? = null,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 1:package com.budgetbook.paymentmethod.service\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 9:import com.budgetbook.paymentmethod.domain.PaymentMethod\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 10:import com.budgetbook.paymentmethod.domain.PaymentMethodType\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 21:        SELECT tr.destinationPaymentMethod.id, COALESCE(SUM(tr.amount), 0)\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 23:        GROUP BY tr.destinationPaymentMethod.id\n  `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` — 28:        SELECT tr.sourcePaymentMethod.id, COALESCE(SUM(tr.amount), 0)\n  `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` — 54:            sourcePaymentMethodId = request.sourcePaymentMethodId,\n  `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` — 55:            destinationPaymentMethodId = request.destinationPaymentMethodId,\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/repository/TransferRepository.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 33개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.532609+09:00","note":"작업 요청 접수: 카테고리/결제수단 (+ 그외) 입력부에서 추가/삭제는 되는데 수정까지 가능하게"},{"step":"audit","at":"2026-04-20T13:41:05.545020+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T13:41:07.476274+09:00","note":"코드 분석: 관련 파일 13개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:09.268471+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:09.334783+09:00","note":"기획서 자동 생성 완료 (4258자)"},{"step":"approved","at":"2026-04-20T13:41:09.862569+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"카테고리 관리 버그"},{"id":"req-1776660064568-024","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"거래 삭제 시 이동 안됨 — 거래 수정 화면에 머무름, 이전으로 가면 'Transaction does not exist' 발생","tags":["navigation_state"],"tags_auto":false,"step":"approved","risk_level":"WARNING","created_at":"2026-04-20T13:41:04.568210+09:00","updated_at":"2026-04-20T14:03:37.552675+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"navigation_state","risk":"WARNING","pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"],"grep_count":2,"lesson_count":3,"tracker_count":2,"tracker_threshold":3}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/login_page.dart","frontend/lib/features/home/presentation/pages/dashboard_page.dart","frontend/lib/core/widgets/item_selector_sheet.dart","frontend/lib/features/auth/presentation/pages/auth_callback_page.dart","frontend/lib/app.dart","frontend/lib/features/home/presentation/widgets/monthly_trend_card.dart","frontend/test/features/auth/presentation/pages/login_page_test.dart","frontend/lib/features/budget/presentation/widgets/budget_suggestion_card.dart","frontend/test/features/onboarding/presentation/pages/onboarding_page_test.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/core/router/app_router.dart","frontend/lib/features/home/presentation/widgets/category_breakdown_card.dart","frontend/lib/core/widgets/error_widget.dart","frontend/lib/core/widgets/account_balance_card.dart","frontend/test/features/auth/presentation/pages/auth_callback_page_test.dart","frontend/test/core/router/app_router_test.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart"],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","hits":1},{"file":"frontend/lib/core/utils/date_helpers.dart","hits":1},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/main_shell_page.dart","hits":1},{"file":"frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/pages/budget_list_page.dart","hits":1},{"file":"frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"does","line":"109:            ?: throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method does not exist.\")"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"does","line":"140:                throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method $id does not exist for this couple.\")"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"does","line":"164:            ?: throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method does not exist.\")"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"22:import com.budgetbook.transfer.repository.TransferRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"34:    private val transferRepository: TransferRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"transfer","line":"55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"21:import com.budgetbook.transaction.repository.TransactionRepository"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"24:import org.springframework.transaction.annotation.Transactional"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"Transaction","line":"33:    private val transactionRepository: TransactionRepository,"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"transfer","line":"64:     * 결제 이체(Transfer with is_card_settlement=true) 생성 시 해당 거래들의 paid_at이 설정됨."},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"1:package com.budgetbook.transaction.domain"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"23:@Table(name = \"transactions\")"},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","term":"Transaction","line":"24:class Transaction("},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","term":"transaction","line":"58:    val transactionIds: List<UUID> = emptyList()"}],"file_count":717,"related_files":["backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt","backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt","frontend/lib/core/utils/date_helpers.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/admin/presentation/pages/admin_dashboard_page.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/lib/features/budget/presentation/widgets/budget_transactions_sheet.dart","backend/src/main/kotlin/com/budgetbook/pocket/service/MoneyPocketService.kt"]},"generated_plan":"# 거래 삭제 시 이동 안됨 — 거래 수정 화면에 머무름, 이전으로 가면 'Transaction does not exist' 발생\n> 2026-04-20 13:41 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\n거래 삭제 시 이동 안됨 — 거래 수정 화면에 머무름, 이전으로 가면 'Transaction does not exist' 발생\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt`** — 키워드 1회 매칭\n- **`frontend/lib/core/utils/date_helpers.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/balance_adjustment_sheet.dart`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 21:import com.budgetbook.transaction.repository.TransactionRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 24:import org.springframework.transaction.annotation.Transactional\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 33:    private val transactionRepository: TransactionRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 109:            ?: throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method does not exist.\")\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 140:                throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method $id does not exist for this couple.\")\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 164:            ?: throw NotFoundException(\"PAYMENT_METHOD_NOT_FOUND\", \"Payment method does not exist.\")\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 22:import com.budgetbook.transfer.repository.TransferRepository\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 34:    private val transferRepository: TransferRepository,\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 55:        val transferIn = transferRepository.sumAmountByDestinationForCouple(coupleId)\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 1:package com.budgetbook.transaction.domain\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 23:@Table(name = \"transactions\")\n  `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` — 24:class Transaction(\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**navigation_state**: 재발 2/3 ⚠ WARNING\n  - ⚠ year/month를 전달하지 않아 항상 현재 달로 로드\n  - ⚠ categoryId/paymentMethodId만 전달하고 기간 정보 누락\n  - ⚠ BE API가 YearMonth.now() 하드코딩\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/domain/Transaction.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/dto/TransferDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/ai/service/AiClassificationService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/utils/date_helpers.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 navigation_state | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:41:04.568210+09:00","note":"작업 요청 접수: 거래 삭제 시 이동 안됨 — 거래 수정 화면에 머무름, 이전으로 가면 'Transaction does not exist' 발생"},{"step":"audit","at":"2026-04-20T13:41:05.580828+09:00","note":"Audit Preview: WARNING (태그: navigation_state)"},{"step":"audit","at":"2026-04-20T13:41:07.734243+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:41:09.362257+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:41:09.385962+09:00","note":"기획서 자동 생성 완료 (4675자)"},{"step":"approved","at":"2026-04-20T13:41:09.896925+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null,"phase":"거래 네비게이션 버그"},{"id":"req-1776660905826-025","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"StatisticsBloc 패턴 확장 — StatisticsFilter value object + currentFilter getter (TransactionBloc 과 동일 패턴)","tags":["filter_propagation"],"tags_auto":false,"step":"review","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T13:55:05.826890+09:00","updated_at":"2026-04-20T14:03:36.961530+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"filter_propagation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"],"grep_count":3,"lesson_count":3,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["backend/src/test/kotlin/com/budgetbook/category/controller/CategoryControllerTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/StatisticsServiceTest.kt","backend/src/main/kotlin/com/budgetbook/budget/controller/BudgetController.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionExportServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/controller/StatisticsControllerTest.kt","backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt","backend/src/main/kotlin/com/budgetbook/admin/controller/AdminController.kt","backend/src/test/kotlin/com/budgetbook/transaction/controller/TransactionControllerTest.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionServiceTest.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/PocketTransferServiceTest.kt","backend/src/test/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/MoneyPocketControllerTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/MoneyPocketServiceTest.kt","backend/src/main/kotlin/com/budgetbook/budget/controller/WeeklySettlementController.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/DistributionRatioServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt"],"keyword_files":[{"file":"frontend/lib/core/bloc/month_sync_handler.dart","hits":3},{"file":"frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","hits":3},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":2},{"file":"frontend/lib/core/di/injection.dart","hits":2},{"file":"frontend/lib/core/router/app_router.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionImportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/JsonLogLayout.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RequestLoggingFilter.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/WebSocketAuthInterceptor.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/dto/AuthDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"currentFilter","line":"71:    // Transaction list — 전체 필터(currentFilter) 유지."},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"currentFilter","line":"77:      final f = txnBloc.currentFilter;"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"object","line":"74:    // TransactionFilter value object 전체로 교체."},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"StatisticsBloc","line":"101:      final statBloc = getIt<StatisticsBloc>();"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"TransactionBloc","line":"76:      final txnBloc = getIt<TransactionBloc>();"},{"file":"frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","term":"currentFilter","line":"32:  TransactionFilter get currentFilter => TransactionFilter("},{"file":"frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","term":"TransactionBloc","line":"9:class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {"},{"file":"frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","term":"TransactionBloc","line":"48:  TransactionBloc({required this.transactionRepository, this.statisticsRepository})"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","term":"object","line":"39:    companion object {"},{"file":"frontend/lib/core/di/injection.dart","term":"StatisticsBloc","line":"209:  getIt.registerLazySingleton<StatisticsBloc>("},{"file":"frontend/lib/core/di/injection.dart","term":"StatisticsBloc","line":"210:    () => StatisticsBloc("},{"file":"frontend/lib/core/di/injection.dart","term":"TransactionBloc","line":"181:  getIt.registerLazySingleton<TransactionBloc>("},{"file":"frontend/lib/core/di/injection.dart","term":"TransactionBloc","line":"182:    () => TransactionBloc("},{"file":"frontend/lib/core/router/app_router.dart","term":"StatisticsBloc","line":"335:                return BlocProvider<StatisticsBloc>("},{"file":"frontend/lib/core/router/app_router.dart","term":"StatisticsBloc","line":"336:                  create: (_) => getIt<StatisticsBloc>()"},{"file":"frontend/lib/core/router/app_router.dart","term":"TransactionBloc","line":"270:                final bloc = getIt<TransactionBloc>();"},{"file":"frontend/lib/core/router/app_router.dart","term":"TransactionBloc","line":"297:                    BlocProvider<TransactionBloc>.value(value: getIt<TransactionBloc>()),"},{"file":"frontend/lib/core/router/app_router.dart","term":"TransactionBloc","line":"382:            BlocProvider<TransactionBloc>.value("}],"file_count":717,"related_files":["frontend/lib/core/bloc/month_sync_handler.dart","frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/core/di/injection.dart","frontend/lib/core/router/app_router.dart","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionImportService.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/config/JsonLogLayout.kt","backend/src/main/kotlin/com/budgetbook/config/RequestLoggingFilter.kt","backend/src/main/kotlin/com/budgetbook/config/WebSocketAuthInterceptor.kt","backend/src/main/kotlin/com/budgetbook/auth/dto/AuthDtos.kt","backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt"]},"generated_plan":"# StatisticsBloc 패턴 확장 — StatisticsFilter value object + currentFilter getter (TransactionBloc 과 동일 패턴)\n> 2026-04-20 13:55 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\nStatisticsBloc 패턴 확장 — StatisticsFilter value object + currentFilter getter (TransactionBloc 과 동일 패턴)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/bloc/month_sync_handler.dart`** — 키워드 3회 매칭\n- **`frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart`** — 키워드 3회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 2회 매칭\n- **`frontend/lib/core/di/injection.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/router/app_router.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionImportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 71:    // Transaction list — 전체 필터(currentFilter) 유지.\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 77:      final f = txnBloc.currentFilter;\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 74:    // TransactionFilter value object 전체로 교체.\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 101:      final statBloc = getIt<StatisticsBloc>();\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 76:      final txnBloc = getIt<TransactionBloc>();\n  `frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart` — 32:  TransactionFilter get currentFilter => TransactionFilter(\n  `frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart` — 9:class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {\n  `frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart` — 48:  TransactionBloc({required this.transactionRepository, this.statisticsRepository})\n  `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` — 39:    companion object {\n  `frontend/lib/core/di/injection.dart` — 209:  getIt.registerLazySingleton<StatisticsBloc>(\n  `frontend/lib/core/di/injection.dart` — 210:    () => StatisticsBloc(\n  `frontend/lib/core/di/injection.dart` — 181:  getIt.registerLazySingleton<TransactionBloc>(\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**filter_propagation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ BLoC 이벤트에는 있으나 Repository 호출에서 누락\n  - ⚠ DataSource에서 API 쿼리 파라미터에 미포함\n  - ⚠ 클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실\n\n## 4. 과거 유사 인시던트\n- [2026-04-14] PeriodSummary 필터(카테고리/결제수단)가 API에 미전달\n- [2026-04-15] LoadCardSettlementSummary year/month 미전달 → 항상 현재 월\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/bloc/month_sync_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/features/transaction/presentation/bloc/transaction_bloc.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n- [ ] `frontend/lib/core/di/injection.dart` 확인 및 수정\n- [ ] `frontend/lib/core/router/app_router.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionImportService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 filter_propagation | 관련 파일 35개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T13:55:05.826890+09:00","note":"작업 요청 접수: StatisticsBloc 패턴 확장 — StatisticsFilter value object + currentFilter getter (TransactionBloc 과 동일 패턴)"},{"step":"audit","at":"2026-04-20T13:55:06.866332+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: filter_propagation)"},{"step":"audit","at":"2026-04-20T13:55:08.595345+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T13:55:09.622366+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T13:55:09.649632+09:00","note":"기획서 자동 생성 완료 (4299자)"},{"step":"approved","at":"2026-04-20T13:55:10.176335+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"review","at":"2026-04-20T13:55:11.531704+09:00","note":"PR push 완료 — fix/statistics-report-filter-pattern branch"}],"error":null,"notes":"PR push 완료 — fix/statistics-report-filter-pattern branch","phase":"Filter 구조 개선"},{"id":"req-1776662298810-001","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"필터에서 '이번 주' 등 날짜 범위 선택 시 목록은 필터되나 총액/집계 계산이 dateFrom/To 미반영 — 월 기준 금액이 그대로 표시됨","tags":["filter_propagation","amount_calculation"],"tags_auto":false,"phase":"기간 필터 집계 버그","parent_request_id":null,"step":"done","risk_level":"STRUCTURAL_FIX_REQUIRED","created_at":"2026-04-20T14:18:18.810621+09:00","updated_at":"2026-04-20T21:08:46.064622+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"filter_propagation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["BLoC 이벤트에는 있으나 Repository 호출에서 누락","DataSource에서 API 쿼리 파라미터에 미포함","클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실"],"grep_count":3,"lesson_count":3,"tracker_count":3,"tracker_threshold":3},{"tag":"amount_calculation","risk":"STRUCTURAL_FIX_REQUIRED","pitfalls":["Transfer(이체) 포함 여부가 서비스마다 다름","Visibility 필터가 Transfer에는 미적용","FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산","카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이"],"grep_count":4,"lesson_count":6,"tracker_count":3,"tracker_threshold":3}],"risk_level":"STRUCTURAL_FIX_REQUIRED","related_lessons":[{"date":"2026-04-14","project":"budget-book","classification":["filter_propagation"],"symptom":"PeriodSummary 필터(카테고리/결제수단)가 API에 미전달","root_cause":"UI에 필터 표시되지만 BLoC→Repo→DataSource 체인에 파라미터 없음","missed_locations":["period_summary_event.dart","period_summary_bloc.dart","statistics_repository.dart","statistics_remote_datasource.dart"],"prevention":"필터 UI 추가 시 반드시 API 전달 체인 동시 구현"},{"date":"2026-04-15","project":"budget-book","classification":["filter_propagation"],"symptom":"LoadCardSettlementSummary year/month 미전달 → 항상 현재 월","root_cause":"_onLoadPaymentMethods에서 add(const LoadCardSettlementSummary()) — year/month 없이 호출","missed_locations":["payment_method_bloc.dart:35"],"prevention":"필수 파라미터는 optional이 아닌 required로 선언. Event→BLoC→Repo→DataSource 체인 전수 확인"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","db_schema"],"symptom":"카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산","root_cause":"Transaction에 paid_at 없음, Transfer에 is_card_settlement 없음 — 데이터 모델 수준의 누락","missed_locations":["Transaction.kt","Transfer.kt","V51-V52","TransferService.createCardSettlement","PaymentMethodService","StatisticsService","ReportService","PaymentMethodStatisticsService"],"prevention":"카드 결제 = 단순 이체가 아닌 원본 거래 결제 완료 처리 필요. 데이터 모델에 상태 필드 먼저 설계. 통계 쿼리는 settlement 제외 버전 사용."},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":["backend/src/test/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodServiceTest.kt","backend/src/test/kotlin/com/budgetbook/pocket/service/MoneyPocketServiceTest.kt","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionExportServiceTest.kt","backend/src/test/kotlin/com/budgetbook/category/controller/CategoryControllerTest.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/PocketTransferControllerTest.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/test/kotlin/com/budgetbook/transaction/service/TransactionImportServiceTest.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","backend/src/test/kotlin/com/budgetbook/pocket/controller/MoneyPocketControllerTest.kt","backend/src/main/kotlin/com/budgetbook/admin/controller/AdminController.kt","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetServiceTest.kt","backend/src/test/kotlin/com/budgetbook/budget/service/BudgetAlertServiceTest.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","frontend/lib/features/statistics/domain/entities/payment_method_statistics.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementSchedulerTest.kt","backend/src/main/kotlin/com/budgetbook/auth/controller/AuthController.kt","backend/src/test/kotlin/com/budgetbook/budget/service/WeeklySettlementServiceTest.kt"],"keyword_files":[{"file":"frontend/lib/core/widgets/account_balance_card.dart","hits":2},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":2},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","hits":2},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","hits":1},{"file":"frontend/lib/core/widgets/month_navigator.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/common/dto/CommonFilterParams.kt","hits":1},{"file":"frontend/lib/core/router/app_router.dart","hits":1},{"file":"frontend/lib/core/models/unified_filter_state.dart","hits":1},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","hits":1},{"file":"frontend/lib/features/statistics/presentation/pages/statistics_page.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/widgets/account_balance_card.dart","term":"Amount","line":"132:    int prevAmount = 0;"},{"file":"frontend/lib/core/widgets/account_balance_card.dart","term":"Amount","line":"133:    int currAmount = 0;"},{"file":"frontend/lib/core/widgets/account_balance_card.dart","term":"Amount","line":"134:    int unpaidAmount = 0;"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"dateFrom","line":"251:                              currentFrom: state.dateFrom,"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"dateFrom","line":"255:                                  dateFrom: from,"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"dateFrom","line":"350:                              dateFrom: state.dateFrom,"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Amount","line":"6:import 'package:budget_book/core/widgets/filters/amount_range_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Amount","line":"32:    if (enabledFilters.contains(FilterType.amountRange) && (state.amountMin != null || state.amountMax != null)) count++;"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Amount","line":"69:    if (enabledFilters.contains(FilterType.amountRange) && (state.amountMin != null || state.amountMax != null)) {"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"dateFrom","line":"72:    // 과거 인시던트(2026-04-15 월 이동 시 dateFrom/To/keyword/pocket/amount/type drop)"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"dateFrom","line":"87:        dateFrom: f.dateFrom,"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"Amount","line":"72:    // 과거 인시던트(2026-04-15 월 이동 시 dateFrom/To/keyword/pocket/amount/type drop)"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"Amount","line":"85:        amountMin: f.amountMin,"},{"file":"frontend/lib/core/bloc/month_sync_handler.dart","term":"Amount","line":"86:        amountMax: f.amountMax,"},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","term":"update","line":"36:  /// preventing duplicate updates from our own changes."},{"file":"frontend/lib/core/websocket/sync_event_handler.dart","term":"update","line":"38:    // Skip events authored by self to avoid duplicate updates"}],"file_count":717,"related_files":["frontend/lib/core/widgets/account_balance_card.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","frontend/lib/core/bloc/month_sync_handler.dart","frontend/lib/core/websocket/sync_event_handler.dart","frontend/lib/core/widgets/month_navigator.dart","backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt","backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt","backend/src/main/kotlin/com/budgetbook/common/dto/CommonFilterParams.kt","frontend/lib/core/router/app_router.dart","frontend/lib/core/models/unified_filter_state.dart","frontend/lib/core/widgets/filters/date_range_filter.dart","frontend/lib/features/statistics/presentation/pages/statistics_page.dart"]},"generated_plan":"# 필터에서 '이번 주' 등 날짜 범위 선택 시 목록은 필터되나 총액/집계 계산이 dateFrom/To 미반영 — 월 기준 금액이 그대로 표시됨\n> 2026-04-20 14:18 | budget-book | 위험도: STRUCTURAL_FIX_REQUIRED\n\n> **🚫 구조적 수정 필수** — 패치 수정 불허. 동일 패턴 재발 3회 이상.\n> 아래 작업 계획에 **구조적 근본 원인 해결 방안**을 포함해야 합니다.\n\n## 1. 증상\n필터에서 '이번 주' 등 날짜 범위 선택 시 목록은 필터되나 총액/집계 계산이 dateFrom/To 미반영 — 월 기준 금액이 그대로 표시됨\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/widgets/account_balance_card.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/bloc/month_sync_handler.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/websocket/sync_event_handler.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/month_navigator.dart`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionService.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/widgets/account_balance_card.dart` — 132:    int prevAmount = 0;\n  `frontend/lib/core/widgets/account_balance_card.dart` — 133:    int currAmount = 0;\n  `frontend/lib/core/widgets/account_balance_card.dart` — 134:    int unpaidAmount = 0;\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 251:                              currentFrom: state.dateFrom,\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 255:                                  dateFrom: from,\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 350:                              dateFrom: state.dateFrom,\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 6:import 'package:budget_book/core/widgets/filters/amount_range_filter.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 32:    if (enabledFilters.contains(FilterType.amountRange) && (state.amountMin != null || state.amountMax != null)) count++;\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 69:    if (enabledFilters.contains(FilterType.amountRange) && (state.amountMin != null || state.amountMax != null)) {\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 72:    // 과거 인시던트(2026-04-15 월 이동 시 dateFrom/To/keyword/pocket/amount/type drop)\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 87:        dateFrom: f.dateFrom,\n  `frontend/lib/core/bloc/month_sync_handler.dart` — 85:        amountMin: f.amountMin,\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**filter_propagation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ BLoC 이벤트에는 있으나 Repository 호출에서 누락\n  - ⚠ DataSource에서 API 쿼리 파라미터에 미포함\n  - ⚠ 클라이언트 사이드 필터링으로 대체 → 페이징과 조합 시 데이터 손실\n**amount_calculation**: 재발 3/3 ⚠ STRUCTURAL_FIX_REQUIRED\n  - ⚠ Transfer(이체) 포함 여부가 서비스마다 다름\n  - ⚠ Visibility 필터가 Transfer에는 미적용\n  - ⚠ FE에서 BE 합계에 다시 Transfer를 더하는 이중 합산\n  - ⚠ 카테고리 기반 집계 vs 전체 집계에서 Transfer 처리 차이\n\n## 4. 과거 유사 인시던트\n- [2026-04-14] PeriodSummary 필터(카테고리/결제수단)가 API에 미전달\n- [2026-04-15] LoadCardSettlementSummary year/month 미전달 → 항상 현재 월\n- [2026-04-15] 카드 결제해도 미결제 금액에 계속 표시 + 결제 이체가 통계에 이중 계산\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/widgets/account_balance_card.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/unified_filter_bar.dart` 확인 및 수정\n- [ ] `frontend/lib/core/bloc/month_sync_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/sync_event_handler.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/month_navigator.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/dto/StatisticsDtos.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 filter_propagation, amount_calculation | 관련 파일 35개 | 소스 717개","step_notes":{"review":[{"type":"artifact","content":"PR: https://github.com/AIVA-SaaS/budget-book/pull/new/fix/date-range-summary","at":"2026-04-20T14:33:41.345376+09:00"}]},"history":[{"step":"request","at":"2026-04-20T14:18:18.810621+09:00","note":"작업 요청 접수: 필터에서 '이번 주' 등 날짜 범위 선택 시 목록은 필터되나 총액/집계 계산이 dateFrom/To 미반영 — 월 기준 금액이 그대로 표시됨"},{"step":"audit","at":"2026-04-20T14:18:19.853419+09:00","note":"Audit Preview: STRUCTURAL_FIX_REQUIRED (태그: filter_propagation, amount_calculation)"},{"step":"audit","at":"2026-04-20T14:18:21.952177+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T14:18:22.980060+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T14:18:23.008113+09:00","note":"기획서 자동 생성 완료 (4526자)"},{"step":"approved","at":"2026-04-20T14:18:23.535821+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."},{"step":"dev","at":"2026-04-20T14:22:25.665675+09:00","note":"승인 → 개발"},{"step":"dev","at":"2026-04-20T14:30:55.254281+09:00","note":"개발 착수 — 날짜 범위 필터 시 집계 총액 재계산"},{"step":"review","at":"2026-04-20T14:33:40.865368+09:00","note":"PR 생성: fix/date-range-summary — TransactionBloc getSummary 에 dateFrom/To 전달"},{"step":"review","at":"2026-04-20T14:33:41.345376+09:00","note":"[artifact] PR: https://github.com/AIVA-SaaS/budget-book/pull/new/fix/date-range-summary"},{"step":"done","at":"2026-04-20T21:08:46.064622+09:00","note":"검증 → 완료"}],"error":null,"notes":"검증 → 완료"},{"id":"req-1776663394879-001","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"하네스 3.1 오케스트레이터 — Claude Code spawn + 실시간 stream + PR 자동화 (5 Sprint 계획)","tags":["meta_process"],"tags_auto":false,"phase":"하네스 고도화 Priority 3","parent_request_id":null,"step":"approved","risk_level":"WARNING","created_at":"2026-04-20T14:36:34.879984+09:00","updated_at":"2026-04-20T14:36:39.784617+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"meta_process","risk":"WARNING","pitfalls":["도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음","메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름"],"grep_count":3,"lesson_count":2,"tracker_count":1,"tracker_threshold":2}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스가 존재했지만 기획서 작성 시 실행되지 않음","root_cause":"하네스 도구를 만들었으나 AI Command Protocol(CLAUDE.md)에 강제 단계로 삽입하지 않음","missed_locations":["CLAUDE.md Step 1~2 사이","MEMORY.md"],"prevention":"도구 생성 시 반드시 CLAUDE.md 프로토콜 + MEMORY.md에 동시 연결. 도구 존재 ≠ 프로세스 강제"},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행","root_cause":"plan-audit.sh Hook은 기획서(_plan.md) 작성 시에만 트리거됨. 기획서 없이 바로 Edit tool 사용하면 우회 가능. PreToolUse(Edit) hook 부재로 CLAUDE.md Step 1/1.5 강제 실패","missed_locations":["PreToolUse Edit hook 없음","CLAUDE.md Step 1 강제 안 됨","사용자가 직접 지적할 때까지 AI가 자체 검증 안 함"],"prevention":"PreToolUse(Edit|Write) hook 추가 — 최근 N분 내에 _plan.md가 작성/수정되지 않았으면 경고. 사용자가 1줄 요청해도 반드시 기획서 작성 후 진행."}]},"code_analysis":{"available":true,"git_log":["ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)","3b583a8 Phase 20 + 20-B: 카드 결제 현황/결제 대상/네비게이션 수정 + 계산기 확장"],"tag_files":[],"keyword_files":[{"file":"frontend/lib/core/router/app_router.dart","hits":2},{"file":"frontend/lib/core/widgets/icon_picker.dart","hits":2},{"file":"frontend/lib/core/websocket/websocket_service.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/BudgetBookApplication.kt","hits":1},{"file":"frontend/lib/core/widgets/amount_input_field.dart","hits":1},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","hits":1},{"file":"frontend/lib/core/services/connectivity_service.dart","hits":1},{"file":"frontend/lib/features/transaction/presentation/pages/transaction_form_page.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/router/app_router.dart","term":"auto","line":"159:      // should always exist after signup. Auto-complete onboarding."},{"file":"frontend/lib/core/router/app_router.dart","term":"auto","line":"168:      // Server state is source of truth: auto-complete onboarding"},{"file":"frontend/lib/core/router/app_router.dart","term":"auto","line":"358:    // auto-close on pop which would permanently kill the singleton."},{"file":"frontend/lib/core/router/app_router.dart","term":"stream","line":"102:/// Adapts a BLoC stream into a [Listenable] for GoRouter.refreshListenable."},{"file":"frontend/lib/core/router/app_router.dart","term":"stream","line":"104:  late final StreamSubscription _subscription;"},{"file":"frontend/lib/core/router/app_router.dart","term":"stream","line":"107:    _subscription = bloc.stream.listen((_) => notifyListeners());"},{"file":"frontend/lib/core/widgets/icon_picker.dart","term":"auto","line":"68:    'auto_stories': Icons.auto_stories,"},{"file":"frontend/lib/core/websocket/websocket_service.dart","term":"stream","line":"22:  final StreamController<SyncEvent> _eventController ="},{"file":"frontend/lib/core/websocket/websocket_service.dart","term":"stream","line":"23:      StreamController<SyncEvent>.broadcast();"},{"file":"frontend/lib/core/websocket/websocket_service.dart","term":"stream","line":"24:  final StreamController<WebSocketConnectionStatus> _statusController ="},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"16:class CardAutoSettlementScheduler("},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"33:        log.info(\"Auto-settlement: found {} cards for settlement day {}\", cards.size, dayOfMonth)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","term":"auto","line":"39:                log.info(\"Auto-settlement: skipping duplicate for card {} ({})\", card.id, card.name)"},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"auto","line":"290:     * Auto-seeds for existing couples that were created before the visibility feature."},{"file":"backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","term":"auto","line":"305:            log.warn(\"Failed to auto-seed private categories for userId={}: {}\", userId, e.message)"}],"file_count":717,"related_files":["frontend/lib/core/router/app_router.dart","frontend/lib/core/widgets/icon_picker.dart","frontend/lib/core/websocket/websocket_service.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt","backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt","backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt","backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt","backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt","backend/src/main/kotlin/com/budgetbook/BudgetBookApplication.kt","frontend/lib/core/widgets/amount_input_field.dart","frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/core/services/connectivity_service.dart","frontend/lib/features/transaction/presentation/pages/transaction_form_page.dart"]},"generated_plan":"# 하네스 3.1 오케스트레이터 — Claude Code spawn + 실시간 stream + PR 자동화 (5 Sprint 계획)\n> 2026-04-20 14:36 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\n하네스 3.1 오케스트레이터 — Claude Code spawn + 실시간 stream + PR 자동화 (5 Sprint 계획)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/router/app_router.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/widgets/icon_picker.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/websocket/websocket_service.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/service/TransferService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transfer/domain/Transfer.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/router/app_router.dart` — 159:      // should always exist after signup. Auto-complete onboarding.\n  `frontend/lib/core/router/app_router.dart` — 168:      // Server state is source of truth: auto-complete onboarding\n  `frontend/lib/core/router/app_router.dart` — 358:    // auto-close on pop which would permanently kill the singleton.\n  `frontend/lib/core/router/app_router.dart` — 102:/// Adapts a BLoC stream into a [Listenable] for GoRouter.refreshListenable.\n  `frontend/lib/core/router/app_router.dart` — 104:  late final StreamSubscription _subscription;\n  `frontend/lib/core/router/app_router.dart` — 107:    _subscription = bloc.stream.listen((_) => notifyListeners());\n  `frontend/lib/core/widgets/icon_picker.dart` — 68:    'auto_stories': Icons.auto_stories,\n  `frontend/lib/core/websocket/websocket_service.dart` — 22:  final StreamController<SyncEvent> _eventController =\n  `frontend/lib/core/websocket/websocket_service.dart` — 23:      StreamController<SyncEvent>.broadcast();\n  `frontend/lib/core/websocket/websocket_service.dart` — 24:  final StreamController<WebSocketConnectionStatus> _statusController =\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 16:class CardAutoSettlementScheduler(\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` — 33:        log.info(\"Auto-settlement: found {} cards for settlement day {}\", cards.size, dayOfMonth)\n\n### 최근 커밋\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n- 015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)\n\n## 3. 위험 평가\n\n**meta_process**: 재발 1/2 ⚠ WARNING\n  - ⚠ 도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음\n  - ⚠ 메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 하네스가 존재했지만 기획서 작성 시 실행되지 않음\n- [2026-04-15] 하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/router/app_router.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/icon_picker.dart` 확인 및 수정\n- [ ] `frontend/lib/core/websocket/websocket_service.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/scheduler/CardAutoSettlementScheduler.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/category/service/CategoryGroupService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/auth/service/CustomOAuth2UserService.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 meta_process | 관련 파일 15개 | 소스 717개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T14:36:34.879984+09:00","note":"작업 요청 접수: 하네스 3.1 오케스트레이터 — Claude Code spawn + 실시간 stream + PR 자동화 (5 Sprint 계획)"},{"step":"audit","at":"2026-04-20T14:36:35.924577+09:00","note":"Audit Preview: WARNING (태그: meta_process)"},{"step":"audit","at":"2026-04-20T14:36:37.883382+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T14:36:38.912639+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T14:36:38.942291+09:00","note":"기획서 자동 생성 완료 (4163자)"},{"step":"approved","at":"2026-04-20T14:36:39.784617+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null},{"id":"req-1776665952477-001","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"필터 > 기간 변경 프리셋 선택 시 외부 시트가 먼저 닫혀 context deactivated → 네트워크 요청 미발화 + 뒤로 불가. 외부 시트 pop 제거, 내부 시트 stack","tags":["ui_pattern","navigation_state"],"tags_auto":false,"phase":"기간 필터 집계 버그","parent_request_id":"req-1776662298810-001","step":"approved","risk_level":"WARNING","created_at":"2026-04-20T15:19:12.477210+09:00","updated_at":"2026-04-20T15:19:17.160128+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3},{"tag":"navigation_state","risk":"WARNING","pitfalls":["year/month를 전달하지 않아 항상 현재 달로 로드","categoryId/paymentMethodId만 전달하고 기간 정보 누락","BE API가 YearMonth.now() 하드코딩"],"grep_count":2,"lesson_count":3,"tracker_count":2,"tracker_threshold":3}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["navigation_state"],"symptom":"홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋","root_cause":"context.push/go에서 year/month 미전달하는 지점 5곳 존재","missed_locations":["dashboard_page.dart:638","dashboard_page.dart:667","dashboard_page.dart:1157","transaction_detail_page.dart:66","transaction_form_page.dart:472"],"prevention":"navigation_helpers.dart 중앙 헬퍼 도입 — year/month required 파라미터로 컴파일 타임 누락 방지"},{"date":"2026-04-15","project":"budget-book","classification":["amount_calculation","navigation_state"],"symptom":"월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요","root_cause":"월 변경 이벤트가 중앙화되지 않음. 각 페이지가 자신이 필요한 BLoC만 reload. 월 의존 BLoC 여러 개일 때 누락 발생","missed_locations":["budget_list_page.dart MonthNavigator","dashboard_page.dart _MonthHeader","account_balance_card.dart unpaid chip"],"prevention":"MonthContext 중앙 Provider 또는 EventBus로 월 변경 broadcast. 모든 월 의존 BLoC이 자동 구독. 페이지마다 수동 reload 제거."}]},"code_analysis":{"available":true,"git_log":["dc7382a Fix/date range summary (#104)","ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)"],"tag_files":["frontend/test/features/auth/presentation/pages/login_page_test.dart","backend/src/test/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodControllerTest.kt","frontend/lib/features/home/presentation/widgets/category_breakdown_card.dart","frontend/lib/features/report/presentation/pages/report_page.dart","frontend/lib/features/category/presentation/pages/category_page.dart","frontend/lib/features/transaction/presentation/pages/transaction_list_page.dart","frontend/lib/features/payment_method/presentation/pages/payment_method_page.dart","backend/src/main/kotlin/com/budgetbook/report/service/ReportService.kt","frontend/lib/features/category_group/presentation/pages/category_group_page.dart","frontend/lib/core/widgets/month_navigator.dart","frontend/lib/core/widgets/item_selector_sheet.dart","frontend/lib/core/widgets/category_group_selector_sheet.dart","frontend/lib/features/budget/presentation/pages/budget_list_page.dart","frontend/test/features/auth/presentation/pages/auth_callback_page_test.dart","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","frontend/lib/features/statistics/presentation/pages/period_summary_page.dart","frontend/lib/features/transfer/presentation/pages/transfer_list_page.dart","frontend/lib/core/widgets/main_shell_page.dart","frontend/lib/features/home/presentation/widgets/monthly_trend_card.dart","frontend/lib/core/widgets/error_widget.dart"],"keyword_files":[{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","hits":2},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionRepository.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RequestLoggingFilter.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/WebMvcConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/WebSocketConfig.kt","hits":1}],"keyword_matches":[{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"Filter","line":"4:/// Shows a date range filter bottom sheet with presets and custom range picker."},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"Filter","line":"7:void showDateRangeFilterSheet({"},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"context","line":"8:  required BuildContext context,"},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"context","line":"26:    Navigator.of(context).pop();"},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"context","line":"31:    context: context,"},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"filter","line":"4:/// Shows a date range filter bottom sheet with presets and custom range picker."},{"file":"frontend/lib/core/widgets/filters/date_range_filter.dart","term":"filter","line":"7:void showDateRangeFilterSheet({"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"2:import 'package:budget_book/core/models/unified_filter_state.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"Filter","line":"4:import 'package:budget_book/core/widgets/filters/category_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"context","line":"85:  Widget build(BuildContext context) {"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"context","line":"102:              onPressed: () => _showAdvancedFilterSheet(context),"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"context","line":"139:  void _showAdvancedFilterSheet(BuildContext context) {"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"2:import 'package:budget_book/core/models/unified_filter_state.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';"},{"file":"frontend/lib/core/widgets/filters/unified_filter_bar.dart","term":"filter","line":"4:import 'package:budget_book/core/widgets/filters/category_filter.dart';"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","term":"Filter","line":"4:import com.budgetbook.common.dto.CommonFilterParams"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","term":"Filter","line":"38:        @ModelAttribute filter: CommonFilterParams"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","term":"Filter","line":"41:            userId, year, month, filter.visibility ?: \"ALL\", filter.dateFrom, filter.dateTo"},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","term":"filter","line":"4:import com.budgetbook.common.dto.CommonFilterParams"}],"file_count":719,"related_files":["frontend/lib/core/widgets/filters/date_range_filter.dart","frontend/lib/core/widgets/filters/unified_filter_bar.dart","backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt","backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt","backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionRepository.kt","backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt","backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","backend/src/main/kotlin/com/budgetbook/config/RequestLoggingFilter.kt","backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","backend/src/main/kotlin/com/budgetbook/config/WebMvcConfig.kt","backend/src/main/kotlin/com/budgetbook/config/WebSocketConfig.kt"]},"generated_plan":"# 필터 > 기간 변경 프리셋 선택 시 외부 시트가 먼저 닫혀 context deactivated → 네트워크 요청 미발화 + 뒤로 불가. 외부 시트 pop 제거, 내부 시트 stack\n> 2026-04-20 15:19 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\n필터 > 기간 변경 프리셋 선택 시 외부 시트가 먼저 닫혀 context deactivated → 네트워크 요청 미발화 + 뒤로 불가. 외부 시트 pop 제거, 내부 시트 stack\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/core/widgets/filters/date_range_filter.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/widgets/filters/unified_filter_bar.dart`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionRepository.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/JpaConfig.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/core/widgets/filters/date_range_filter.dart` — 4:/// Shows a date range filter bottom sheet with presets and custom range picker.\n  `frontend/lib/core/widgets/filters/date_range_filter.dart` — 7:void showDateRangeFilterSheet({\n  `frontend/lib/core/widgets/filters/date_range_filter.dart` — 8:  required BuildContext context,\n  `frontend/lib/core/widgets/filters/date_range_filter.dart` — 26:    Navigator.of(context).pop();\n  `frontend/lib/core/widgets/filters/date_range_filter.dart` — 31:    context: context,\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 2:import 'package:budget_book/core/models/unified_filter_state.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 3:import 'package:budget_book/core/widgets/filters/date_range_filter.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 4:import 'package:budget_book/core/widgets/filters/category_filter.dart';\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 85:  Widget build(BuildContext context) {\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 102:              onPressed: () => _showAdvancedFilterSheet(context),\n  `frontend/lib/core/widgets/filters/unified_filter_bar.dart` — 139:  void _showAdvancedFilterSheet(BuildContext context) {\n  `backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt` — 4:import com.budgetbook.common.dto.CommonFilterParams\n\n### 최근 커밋\n- dc7382a Fix/date range summary (#104)\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n**navigation_state**: 재발 2/3 ⚠ WARNING\n  - ⚠ year/month를 전달하지 않아 항상 현재 달로 로드\n  - ⚠ categoryId/paymentMethodId만 전달하고 기간 정보 누락\n  - ⚠ BE API가 YearMonth.now() 하드코딩\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 홈/예산 월 이동 후 거래 이동 시 현재 월로 리셋\n- [2026-04-15] 월 이동 시 카드 요약이 예산/홈 페이지에서 stale — 각 페이지마다 수동 reload 필요\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/core/widgets/filters/date_range_filter.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/filters/unified_filter_bar.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/PaymentMethodStatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/statistics/service/StatisticsService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionRepository.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/repository/TransactionSpecifications.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern, navigation_state | 관련 파일 35개 | 소스 719개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T15:19:12.477210+09:00","note":"작업 요청 접수: 필터 > 기간 변경 프리셋 선택 시 외부 시트가 먼저 닫혀 context deactivated → 네트워크 요청 미발화 + 뒤로 불가. 외부 시트 pop 제거, 내부 시트 stack"},{"step":"audit","at":"2026-04-20T15:19:13.494357+09:00","note":"Audit Preview: WARNING (태그: ui_pattern, navigation_state)"},{"step":"audit","at":"2026-04-20T15:19:15.605578+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T15:19:16.616848+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T15:19:16.629313+09:00","note":"기획서 자동 생성 완료 (4533자)"},{"step":"approved","at":"2026-04-20T15:19:17.160128+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null},{"id":"req-1776666470935-002","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"Frontend CI 속도 개선 — build web 제거, analyze/test 병렬, PR only (5분 → 1분)","tags":["meta_process"],"tags_auto":false,"phase":"CI/CD 최적화","parent_request_id":null,"step":"approved","risk_level":"WARNING","created_at":"2026-04-20T15:27:50.935119+09:00","updated_at":"2026-04-20T15:27:54.658275+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"meta_process","risk":"WARNING","pitfalls":["도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음","메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름"],"grep_count":3,"lesson_count":2,"tracker_count":1,"tracker_threshold":2}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스가 존재했지만 기획서 작성 시 실행되지 않음","root_cause":"하네스 도구를 만들었으나 AI Command Protocol(CLAUDE.md)에 강제 단계로 삽입하지 않음","missed_locations":["CLAUDE.md Step 1~2 사이","MEMORY.md"],"prevention":"도구 생성 시 반드시 CLAUDE.md 프로토콜 + MEMORY.md에 동시 연결. 도구 존재 ≠ 프로세스 강제"},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행","root_cause":"plan-audit.sh Hook은 기획서(_plan.md) 작성 시에만 트리거됨. 기획서 없이 바로 Edit tool 사용하면 우회 가능. PreToolUse(Edit) hook 부재로 CLAUDE.md Step 1/1.5 강제 실패","missed_locations":["PreToolUse Edit hook 없음","CLAUDE.md Step 1 강제 안 됨","사용자가 직접 지적할 때까지 AI가 자체 검증 안 함"],"prevention":"PreToolUse(Edit|Write) hook 추가 — 최근 N분 내에 _plan.md가 작성/수정되지 않았으면 경고. 사용자가 1줄 요청해도 반드시 기획서 작성 후 진행."}]},"code_analysis":{"available":true,"git_log":["dc7382a Fix/date range summary (#104)","ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회","9ab1147 fix: V53 마이그레이션 — 기존 BANK→CREDIT 이체 카드 결제로 재분류 + paid_at 자동 설정","a81d9d9 fix: 카드 결제 완료 상태 + 이중 계산 방지 — 구조적 수정 (Phase 20-C)"],"tag_files":[],"keyword_files":[{"file":"backend/src/main/kotlin/com/budgetbook/pocket/controller/MoneyPocketController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","hits":2},{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/category/controller/CategoryGroupController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/service/JwtTokenProvider.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/service/UserCacheService.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt","hits":1}],"keyword_matches":[{"file":"backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","term":"only","line":"25:    @Transactional(readOnly = true)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"only","line":"38:    @Transactional(readOnly = true)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"only","line":"199:    @Transactional(readOnly = true)"},{"file":"backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","term":"only","line":"231:    @Transactional(readOnly = true)"}],"file_count":719,"related_files":["backend/src/main/kotlin/com/budgetbook/pocket/controller/MoneyPocketController.kt","backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt","backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt","backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt","backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt","backend/src/main/kotlin/com/budgetbook/category/controller/CategoryGroupController.kt","backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt","backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt","backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt","backend/src/main/kotlin/com/budgetbook/auth/service/JwtTokenProvider.kt","backend/src/main/kotlin/com/budgetbook/auth/service/UserCacheService.kt","backend/src/main/kotlin/com/budgetbook/transfer/controller/TransferController.kt","backend/src/main/kotlin/com/budgetbook/statistics/controller/StatisticsController.kt"]},"generated_plan":"# Frontend CI 속도 개선 — build web 제거, analyze/test 병렬, PR only (5분 → 1분)\n> 2026-04-20 15:27 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\nFrontend CI 속도 개선 — build web 제거, analyze/test 병렬, PR only (5분 → 1분)\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`backend/src/main/kotlin/com/budgetbook/pocket/controller/MoneyPocketController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt`** — 키워드 2회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/category/controller/CategoryGroupController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/auth/security/CookieOAuth2AuthorizationRequestRepository.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` — 25:    @Transactional(readOnly = true)\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 38:    @Transactional(readOnly = true)\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 199:    @Transactional(readOnly = true)\n  `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` — 231:    @Transactional(readOnly = true)\n\n### 최근 커밋\n- dc7382a Fix/date range summary (#104)\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n- 274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)\n- 133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)\n\n## 3. 위험 평가\n\n**meta_process**: 재발 1/2 ⚠ WARNING\n  - ⚠ 도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음\n  - ⚠ 메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 하네스가 존재했지만 기획서 작성 시 실행되지 않음\n- [2026-04-15] 하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `backend/src/main/kotlin/com/budgetbook/pocket/controller/MoneyPocketController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/controller/TransactionController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/transaction/service/TransactionExportService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/controller/PaymentMethodController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/paymentmethod/service/PaymentMethodService.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/category/controller/CategoryController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/category/controller/CategoryGroupController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/RedisConfig.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 meta_process | 관련 파일 15개 | 소스 719개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T15:27:50.935119+09:00","note":"작업 요청 접수: Frontend CI 속도 개선 — build web 제거, analyze/test 병렬, PR only (5분 → 1분)"},{"step":"audit","at":"2026-04-20T15:27:51.946000+09:00","note":"Audit Preview: WARNING (태그: meta_process)"},{"step":"audit","at":"2026-04-20T15:27:53.120473+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T15:27:54.127887+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T15:27:54.135607+09:00","note":"기획서 자동 생성 완료 (3479자)"},{"step":"approved","at":"2026-04-20T15:27:54.658275+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null},{"id":"req-1776667914416-003","project_id":"19d5b0561a88","project_name":"budget-book","project_root":"/Users/kdh/kdh/github/AIVA-SaaS/budget-book","description":"NAS 배포 시간 단축 — test gates 제거(CI 중복), paths-filter 영역별 배포, BuildKit cache, health check 간격 단축","tags":["meta_process"],"tags_auto":false,"phase":"CI/CD 최적화","parent_request_id":null,"step":"approved","risk_level":"WARNING","created_at":"2026-04-20T15:51:54.416809+09:00","updated_at":"2026-04-20T15:51:59.698609+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"meta_process","risk":"WARNING","pitfalls":["도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음","메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름"],"grep_count":3,"lesson_count":2,"tracker_count":1,"tracker_threshold":2}],"risk_level":"WARNING","related_lessons":[{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스가 존재했지만 기획서 작성 시 실행되지 않음","root_cause":"하네스 도구를 만들었으나 AI Command Protocol(CLAUDE.md)에 강제 단계로 삽입하지 않음","missed_locations":["CLAUDE.md Step 1~2 사이","MEMORY.md"],"prevention":"도구 생성 시 반드시 CLAUDE.md 프로토콜 + MEMORY.md에 동시 연결. 도구 존재 ≠ 프로세스 강제"},{"date":"2026-04-15","project":"budget-book","classification":["meta_process"],"symptom":"하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행","root_cause":"plan-audit.sh Hook은 기획서(_plan.md) 작성 시에만 트리거됨. 기획서 없이 바로 Edit tool 사용하면 우회 가능. PreToolUse(Edit) hook 부재로 CLAUDE.md Step 1/1.5 강제 실패","missed_locations":["PreToolUse Edit hook 없음","CLAUDE.md Step 1 강제 안 됨","사용자가 직접 지적할 때까지 AI가 자체 검증 안 함"],"prevention":"PreToolUse(Edit|Write) hook 추가 — 최근 N분 내에 _plan.md가 작성/수정되지 않았으면 경고. 사용자가 1줄 요청해도 반드시 기획서 작성 후 진행."}]},"code_analysis":{"available":true,"git_log":["294f39a Chore/fast frontend ci (#108)","2d50bef Fix/date range filter navigation (#107)","dc7382a Fix/date range summary (#104)","ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)","5ec479f Fix/card settlement transaction sync (#102)","274a573 fix: 월 변경 반영 3개 결함 수정 — AccountBalanceCard BlocBuilder + MonthSyncHandler 보강 (Phase 20-I)","133de46 fix: MonthNavigator MonthCubit.state 표시 + BE 미결제 transferOut 제거 (Phase 20-H)","015024e feat: MonthCubit 전체 페이지 통합 — 6개 페이지 + MonthSyncHandler 확장 (Phase 20-G)","b49d080 feat: MonthCubit 중앙화 — 월 변경 시 관련 BLoC 자동 동기화 (Phase 20-F 구조적 수정)","b078be3 fix: 자산 현황 카드의 '미결제' 표시 수정 + 홈/예산 월 이동 시 카드 요약 재조회"],"tag_files":[],"keyword_files":[{"file":"frontend/lib/features/auth/presentation/pages/login_page.dart","hits":2},{"file":"frontend/lib/core/network/auth_interceptor.dart","hits":1},{"file":"frontend/lib/core/widgets/error_widget.dart","hits":1},{"file":"frontend/lib/l10n/app_localizations.dart","hits":1},{"file":"frontend/lib/app.dart","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/HealthController.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/common/security/OwnershipValidator.kt","hits":1},{"file":"backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","hits":1},{"file":"frontend/lib/core/router/app_router.dart","hits":1},{"file":"frontend/lib/core/services/connectivity_service.dart","hits":1},{"file":"frontend/lib/core/widgets/balance_adjustment_sheet.dart","hits":1},{"file":"frontend/lib/core/widgets/calculator_amount_field.dart","hits":1},{"file":"frontend/lib/core/widgets/category_group_selector_sheet.dart","hits":1}],"keyword_matches":[{"file":"frontend/lib/features/auth/presentation/pages/login_page.dart","term":"test","line":"19:  State<LoginPage> createState() => _LoginPageState();"},{"file":"frontend/lib/features/auth/presentation/pages/login_page.dart","term":"health","line":"208:      // Quick health check first"},{"file":"frontend/lib/features/auth/presentation/pages/login_page.dart","term":"health","line":"210:        '${ApiEndpoints.baseUrl}/actuator/health',"},{"file":"frontend/lib/features/auth/presentation/pages/login_page.dart","term":"health","line":"238:          '${ApiEndpoints.baseUrl}/actuator/health',"},{"file":"frontend/lib/core/network/auth_interceptor.dart","term":"gates","line":"140:    // Dispatch logout event to AuthBloc so the app navigates to login"},{"file":"frontend/lib/core/widgets/error_widget.dart","term":"gates","line":"17:  /// Whether to show a \"홈으로\" (go home) button that navigates to '/home'."},{"file":"frontend/lib/l10n/app_localizations.dart","term":"gates","line":"17:/// `localizationDelegates` list, and the locales they support in the app's"},{"file":"frontend/lib/l10n/app_localizations.dart","term":"gates","line":"24:///   localizationsDelegates: AppLocalizations.localizationsDelegates,"},{"file":"frontend/lib/l10n/app_localizations.dart","term":"gates","line":"78:  /// delegates."},{"file":"frontend/lib/app.dart","term":"gates","line":"94:                localizationsDelegates: const ["},{"file":"frontend/lib/app.dart","term":"test","line":"20:  State<BudgetBookApp> createState() => _BudgetBookAppState();"},{"file":"frontend/lib/app.dart","term":"test","line":"38:    // when disposeAllSingletons() is called (e.g., in tests or app shutdown)."}],"file_count":719,"related_files":["frontend/lib/features/auth/presentation/pages/login_page.dart","frontend/lib/core/network/auth_interceptor.dart","frontend/lib/core/widgets/error_widget.dart","frontend/lib/l10n/app_localizations.dart","frontend/lib/app.dart","backend/src/main/kotlin/com/budgetbook/config/HealthController.kt","backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt","backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt","backend/src/main/kotlin/com/budgetbook/common/security/OwnershipValidator.kt","backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt","frontend/lib/core/router/app_router.dart","frontend/lib/core/services/connectivity_service.dart","frontend/lib/core/widgets/balance_adjustment_sheet.dart","frontend/lib/core/widgets/calculator_amount_field.dart","frontend/lib/core/widgets/category_group_selector_sheet.dart"]},"generated_plan":"# NAS 배포 시간 단축 — test gates 제거(CI 중복), paths-filter 영역별 배포, BuildKit cache, health check 간격 단축\n> 2026-04-20 15:51 | budget-book | 위험도: WARNING\n\n> **⚠ 주의** — 과거 유사 인시던트 존재. 전수 조사 범위를 확대하고 재발 방지 설계를 포함하세요.\n\n## 1. 증상\nNAS 배포 시간 단축 — test gates 제거(CI 중복), paths-filter 영역별 배포, BuildKit cache, health check 간격 단축\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n- **`frontend/lib/features/auth/presentation/pages/login_page.dart`** — 키워드 2회 매칭\n- **`frontend/lib/core/network/auth_interceptor.dart`** — 키워드 1회 매칭\n- **`frontend/lib/core/widgets/error_widget.dart`** — 키워드 1회 매칭\n- **`frontend/lib/l10n/app_localizations.dart`** — 키워드 1회 매칭\n- **`frontend/lib/app.dart`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/HealthController.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/common/security/OwnershipValidator.kt`** — 키워드 1회 매칭\n- **`backend/src/main/kotlin/com/budgetbook/common/ratelimit/RateLimitAspect.kt`** — 키워드 1회 매칭\n\n### 코드 검색 결과\n  `frontend/lib/features/auth/presentation/pages/login_page.dart` — 19:  State<LoginPage> createState() => _LoginPageState();\n  `frontend/lib/features/auth/presentation/pages/login_page.dart` — 208:      // Quick health check first\n  `frontend/lib/features/auth/presentation/pages/login_page.dart` — 210:        '${ApiEndpoints.baseUrl}/actuator/health',\n  `frontend/lib/features/auth/presentation/pages/login_page.dart` — 238:          '${ApiEndpoints.baseUrl}/actuator/health',\n  `frontend/lib/core/network/auth_interceptor.dart` — 140:    // Dispatch logout event to AuthBloc so the app navigates to login\n  `frontend/lib/core/widgets/error_widget.dart` — 17:  /// Whether to show a \"홈으로\" (go home) button that navigates to '/home'.\n  `frontend/lib/l10n/app_localizations.dart` — 17:/// `localizationDelegates` list, and the locales they support in the app's\n  `frontend/lib/l10n/app_localizations.dart` — 24:///   localizationsDelegates: AppLocalizations.localizationsDelegates,\n  `frontend/lib/l10n/app_localizations.dart` — 78:  /// delegates.\n  `frontend/lib/app.dart` — 94:                localizationsDelegates: const [\n  `frontend/lib/app.dart` — 20:  State<BudgetBookApp> createState() => _BudgetBookAppState();\n  `frontend/lib/app.dart` — 38:    // when disposeAllSingletons() is called (e.g., in tests or app shutdown).\n\n### 최근 커밋\n- 294f39a Chore/fast frontend ci (#108)\n- 2d50bef Fix/date range filter navigation (#107)\n- dc7382a Fix/date range summary (#104)\n- ef62759 fix(transaction): 월 변경 시 필터 drop 방지 + 카테고리 필터 크래시 (#103)\n- 5ec479f Fix/card settlement transaction sync (#102)\n\n## 3. 위험 평가\n\n**meta_process**: 재발 1/2 ⚠ WARNING\n  - ⚠ 도구 존재 ≠ 프로세스 강제: 스크립트만 만들고 프로토콜에 안 넣으면 사용되지 않음\n  - ⚠ 메모리에 등록하지 않으면 다음 세션에서 존재 자체를 모름\n\n## 4. 과거 유사 인시던트\n- [2026-04-15] 하네스가 존재했지만 기획서 작성 시 실행되지 않음\n- [2026-04-15] 하네스 인프라가 있음에도 예산 페이지 버그 수정 시 기획서 작성 + 하네스 체크 없이 바로 코드 수정 진행\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] `frontend/lib/features/auth/presentation/pages/login_page.dart` 확인 및 수정\n- [ ] `frontend/lib/core/network/auth_interceptor.dart` 확인 및 수정\n- [ ] `frontend/lib/core/widgets/error_widget.dart` 확인 및 수정\n- [ ] `frontend/lib/l10n/app_localizations.dart` 확인 및 수정\n- [ ] `frontend/lib/app.dart` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/HealthController.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/config/SecurityConfig.kt` 확인 및 수정\n- [ ] `backend/src/main/kotlin/com/budgetbook/auth/security/JwtAuthenticationFilter.kt` 확인 및 수정\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 meta_process | 관련 파일 15개 | 소스 719개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T15:51:54.416809+09:00","note":"작업 요청 접수: NAS 배포 시간 단축 — test gates 제거(CI 중복), paths-filter 영역별 배포, BuildKit cache, health check 간격 단축"},{"step":"audit","at":"2026-04-20T15:51:55.466290+09:00","note":"Audit Preview: WARNING (태그: meta_process)"},{"step":"audit","at":"2026-04-20T15:51:57.385530+09:00","note":"코드 분석: 관련 파일 15개, 커밋 10건"},{"step":"plan","at":"2026-04-20T15:51:58.417633+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T15:51:58.956036+09:00","note":"기획서 자동 생성 완료 (3762자)"},{"step":"approved","at":"2026-04-20T15:51:59.698609+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null},{"id":"req-1776687706916-005","project_id":"e58345f4e56c","project_name":"calynda","project_root":"/Users/kdh/kdh/github/calynda","description":"일정 추가해도 작업이 생성되었습니다.만 나오면서 실제로 보이지 않는다. 또한 등록할 때 종료가 자꾸 하루 전으로 등록되어 날짜를 수정해야한다.","tags":["ui_pattern"],"tags_auto":true,"phase":null,"parent_request_id":null,"step":"approved","risk_level":"OK","created_at":"2026-04-20T21:21:46.916081+09:00","updated_at":"2026-04-20T21:21:50.713775+09:00","plan_path":"","audit_preview":{"tags":[{"tag":"ui_pattern","risk":"OK","pitfalls":["위젯에 파라미터 추가 후 일부 호출처만 업데이트","모바일 화면에서 공간 부족 고려 누락"],"grep_count":2,"lesson_count":0,"tracker_count":0,"tracker_threshold":3}],"risk_level":"OK","related_lessons":[]},"code_analysis":{"available":true,"git_log":["211f5b5 feat: NAS 배포 인프라 구성 (calynda.duckdns.org)","73c2254 be 용 environment 추가","0ba0043 migrate fe command into fe build process","f84e62b fe 서버 유지를 위한 python 추가","eb89195 불필요한 python 코드 제거","94c6115 fe command 명령어 수정","5f18957 pass LOGIN_SERVER_JWKS_URI to be","b1efe00 add login-server, login-db and fe docker compose services","38bf60e calynda-infra init (init.sh & 전체 docker-compose.yml)"],"tag_files":[],"keyword_files":[],"keyword_matches":[],"file_count":255,"related_files":[]},"generated_plan":"# 일정 추가해도 작업이 생성되었습니다.만 나오면서 실제로 보이지 않는다. 또한 등록할 때 종료가 자꾸 하루 전으로 등록되어 날짜를 수정해야한다.\n> 2026-04-20 21:21 | calynda | 위험도: OK\n\n## 1. 증상\n일정 추가해도 작업이 생성되었습니다.만 나오면서 실제로 보이지 않는다. 또한 등록할 때 종료가 자꾸 하루 전으로 등록되어 날짜를 수정해야한다.\n\n## 2. 코드 분석 결과\n\n### 핵심 관련 파일 (키워드 매칭 상위)\n(관련 파일을 찾지 못했습니다)\n\n\n\n### 최근 커밋\n- 211f5b5 feat: NAS 배포 인프라 구성 (calynda.duckdns.org)\n- 73c2254 be 용 environment 추가\n- 0ba0043 migrate fe command into fe build process\n- f84e62b fe 서버 유지를 위한 python 추가\n- eb89195 불필요한 python 코드 제거\n\n## 3. 위험 평가\n\n**ui_pattern**: 재발 0/3\n  - ⚠ 위젯에 파라미터 추가 후 일부 호출처만 업데이트\n  - ⚠ 모바일 화면에서 공간 부족 고려 누락\n\n\n\n## 5. 작업 계획\n위 코드 분석 결과를 기반으로 수정이 필요한 파일과 작업을 확인하세요.\n\n- [ ] 관련 파일 확인 후 작성\n\n## 6. 검증 계획\n- [ ] 수정된 파일의 기존 동작 영향 확인\n- [ ] 테스트 통과\n- [ ] 실제 시나리오 재현 → 수정 후 정상 동작 확인\n\n---\n**하네스 분석**: 태그 ui_pattern | 관련 파일 0개 | 소스 255개","step_notes":{},"history":[{"step":"request","at":"2026-04-20T21:21:46.916081+09:00","note":"작업 요청 접수: 일정 추가해도 작업이 생성되었습니다.만 나오면서 실제로 보이지 않는다. 또한 등록할 때 종료가 자꾸 하루 전으로 등록되어 날짜를 수정해야한다."},{"step":"audit","at":"2026-04-20T21:21:47.965699+09:00","note":"Audit Preview: OK (태그: ui_pattern)"},{"step":"audit","at":"2026-04-20T21:21:49.074903+09:00","note":"코드 분석: 관련 파일 0개, 커밋 9건"},{"step":"plan","at":"2026-04-20T21:21:50.108950+09:00","note":"기획서 생성 중..."},{"step":"plan","at":"2026-04-20T21:21:50.142638+09:00","note":"기획서 자동 생성 완료 (787자)"},{"step":"approved","at":"2026-04-20T21:21:50.713775+09:00","note":"기획서 검토 후 승인/수정/반려를 선택하세요."}],"error":null}],"pipeline_steps":[{"id":"request","label":"요청 접수","desc":"작업 내용 입력"},{"id":"context","label":"컨텍스트 수집","desc":"프로젝트 현황, 이전 세션, 기술 부채 확인"},{"id":"audit","label":"Scope Audit","desc":"변경 영향 범위 전수 조사 + 재발 위험 판정"},{"id":"plan","label":"기획 검증","desc":"기획서 작성 + 성능 설계 + 하네스 결과 반영"},{"id":"approved","label":"승인 대기","desc":"사용자 승인/수정/재기획 결정"},{"id":"dev","label":"개발","desc":"승인된 기획서 기반 구현"},{"id":"review","label":"교차 검증","desc":"BE↔FE↔Spec 일치, 테스트, 보안 확인"},{"id":"done","label":"완료","desc":"배포 + 라이브 검증"}],"analytics":{"total_entries":4119,"days":{"2026-04-06":46,"2026-04-07":264,"2026-04-08":175,"2026-04-09":258,"2026-04-10":138,"2026-04-11":293,"2026-04-12":519,"2026-04-13":144,"2026-04-14":401,"2026-04-15":510,"2026-04-16":151,"2026-04-17":283,"2026-04-19":224,"2026-04-20":480,"2026-04-21":233},"tools":{"Bash":4119},"projects":{"budget-book":1151,"wemeet-b2b-backend":651,"tiggle":416,"calynda":235}},"daily":[{"date":"2026-04-06","count":46},{"date":"2026-04-07","count":264},{"date":"2026-04-08","count":175},{"date":"2026-04-09","count":258},{"date":"2026-04-10","count":138},{"date":"2026-04-11","count":293},{"date":"2026-04-12","count":519},{"date":"2026-04-13","count":144},{"date":"2026-04-14","count":401},{"date":"2026-04-15","count":510},{"date":"2026-04-16","count":151},{"date":"2026-04-17","count":283},{"date":"2026-04-19","count":224},{"date":"2026-04-20","count":480},{"date":"2026-04-21","count":233}],"health":{"status":"ok","timestamp":"2026-04-21T19:10:48.674270+09:00","data_dir":"/data"},"server_time":1776766248.6742878}