Files
sodalive-ios/docs/20261016_유저_크리에이터_채팅_날짜_구분선/plan-task.md
T

25 KiB
Raw Blame History

유저-크리에이터 채팅 날짜 구분선 구현 계획

상태: 구현 완료 / P1-GATE 실서버·접근성 QA 대기

문서 항목 내용
작성일 2026-10-16
요구사항 기준 prd.md, DATE-001~008
API 기준 해당 없음, 기존 메시지 timestamp 활용
현재 Phase Phase 1, 구현 완료 / 최종 QA 대기
현재 활성 Goal 없음. P1-GATE 외부 조건 대기

목표

유저-크리에이터 DM에서 표시되는 TEXT 메시지를 열람 기기의 현지 날짜 및 앱 언어로 구분하고, 페이지 병합과 ACK 갱신 후에도 구분이 정확하며 메시지 스크롤과 이전 메시지 로드를 유지한다.

현재 상태

Phase 상태 완료 Task 활성/다음 Goal 차단 또는 남은 조건
1 외부 조건 대기 2/2 P1-GATE 실제 DM 계정·방 데이터와 VoiceOver 수동 검증 필요
  • 2026-10-16 사용자 구현 요청으로 P1-T1을 시작한다. 완료한 항목만 검증 증거와 함께 갱신한다.
  • Goal 실행 체계나 token budget은 설정하지 않는다.

범위

포함

  • 표시 TEXT 메시지 기준 날짜 행 파생, 인접한 현지 날짜 변경 지점과 현재 첫 메시지 위에 날짜 구분 항목 표시.
  • 앱 환경 locale에 맞춘 연·월·일·요일 문자열과 기기 시간대 기준 그룹핑.
  • 시간대, DST, locale, 과거 페이지 병합, 보류 메시지 상태 스냅샷 검증 및 SwiftUI 접근성 표시.
  • SodaLive와 SodaLive-dev 타깃의 신규 Swift 파일 등록과 두 타깃 빌드, 지정 수동 QA.

제외

  • 요청 범위 밖 제품 코드·테스트·프로젝트 설정 변경. 이전 문서 전용 제한은 사용자 구현 요청으로 해제했다.
  • API 변경, 메시지별 기존 시각 포맷 변경, 언어 서비스 또는 DateExtension 변경.
  • VOICE 표시, 날짜 고정 헤더, 별도 ViewModel/DTO, 메시지 정렬·중복 제거·ACK 로직 변경, 네트워크 모킹 및 재시도 UI.
  • 사용자에게 확정받지 않은 별도 디자인 시스템이나 픽셀 사양 확장. 구체 스타일은 기존 앱 디자인 관례를 따르는 구현 판단이다.

기술적 제약과 구조

  • 기술 스택: iOS 16.6 이상, Swift language version 5.0, Foundation, SwiftUI, 기존 work/tests의 swiftc 기반 계약 검사 패턴. 테스트 타깃이나 외부 의존성은 추가하지 않는다.
  • locale은 RoomView의 @Environment(\.locale)에서 소비한다. 앱 루트의 LanguageContainer.environment.locale 주입을 이용하며 언어 매핑을 복제하거나 Locale.current를 새 날짜 구현에 사용하지 않는다.
  • RoomView는 @Environment(\.timeZone)을 사용한다. 그룹핑과 포맷 양쪽에서 전달된 Calendar의 사본을 지정 timeZone으로 정규화한다.
  • formatter는 호출마다 설정된 DateFormatter를 쓰고 locale, calendar, timeZone을 적용한 뒤 setLocalizedDateFormatFromTemplate("yMMMMdEEEE")를 호출한다. 상대 날짜, 하드코딩된 언어 조각, 공유 mutable cache를 추가하지 않는다.
  • 행은 현재 표시 목록에서 파생한다. TEXT만 필터링한 뒤 원래 순서와 ID를 유지하고, Date(timeIntervalSince1970: TimeInterval(createdAt) / 1000)으로 표시 메시지마다 한 번 변환한다. 정렬, 별도 날짜 섹션, 상태 저장은 하지 않는다.
  • 첫 표시 행은 항상 날짜를 갖고, 후속 행은 직전 표시 TEXT와 Calendar.isDate(_:inSameDayAs:)가 false일 때만 날짜를 갖는다. 빈 입력에는 행이 없다.
  • 확인된 앱 파일 책임: SodaLive/Sources/V2/Main/Chat/UserCreatorChat/Models/UserCreatorChatModels.swift, Models/UserCreatorChatDisplayMessage.swift, UserCreatorChatRoomView.swift, UserCreatorChatRoomViewModel.swift, 기존 Components/UserCreatorChatTextMessageItemView.swift. 루트 locale 주입은 SodaLive/Sources/App/SodaLiveApp.swift에서 확인한다.

집중 검증 항목

위험 입력·조건 확인할 동작 담당 검증
앱 언어와 기기 지역 불일치 언어는 앱 locale, 날짜 경계는 기기 timeZone P1-T1, Gate 언어 QA
UTC 자정·현지 자정·DST 24시간 차이나 UTC 날짜가 아닌 같은 현지 일자 비교 P1-T2 날짜 경계 assertion
과거 페이지가 같은 날짜에 이어짐 첫 날짜 항목 이동, 중복 없음, 읽던 위치 유지 P1-T2 prepend assertion, Gate 스크롤 QA
pending이 서버의 다른 날짜로 확정됨 기존 빈 날짜 제거와 새 묶음 중복 방지 P1-T2 ACK 스냅샷, Gate 서버 QA
날짜 항목 높이가 기존 viewport를 채움 첫 메시지 paging·짧은 목록 추가 로드·바닥 이동 보존 P1-T2 hook 연결 확인, Gate 실제 화면 QA

Phase 1

Phase 결과: TEXT 메시지의 날짜 문자열과 파생 행·비고정 UI가 정확히 동작하며 기존 채팅 열람 흐름을 보존한다.

선행조건: 사용자 구현 착수 요청과 본 PRD의 확정 요구사항.

Phase 완료 조건: P1-T1, P1-T2, P1-GATE 완료, 검증 기록 누적.

구현 항목

Task 1.1 날짜 표현 formatter

Goal P1-T1: 지정된 앱 locale, calendar, 기기 timeZone에 따라 상대 표현 없이 날짜 전체를 문자열로 만든다.

  • 시작 조건: DATE-002~004 확정, P1-T2 전에 완료.
  • 완료 증거: RED/GREEN/REFACTOR 체크 전체, 셸 검사 성공, 양쪽 앱 타깃에 신규 소스 등록.
  • 범위 밖: 날짜 묶음 계산과 UI.

Files:

  • Create: SodaLive/Sources/V2/Main/Chat/UserCreatorChat/Models/UserCreatorChatDatePresentation.swift (향후 신규)
  • Modify: SodaLive.xcodeproj/project.pbxproj (신규 파일을 SodaLive와 SodaLive-dev Sources 양쪽에 등록)
  • Create: work/tests/UserCreatorChatDatePresentationCheck.swift (향후 신규)
  • Create: work/tests/check-user-creator-chat-date-presentation.sh (향후 신규)
  • Reference: work/tests/check-gift-decoding-contract.sh (임시 바이너리 컴파일 및 정리 패턴)

Runner는 swiftc -swift-version 5로 Models/UserCreatorChatModels.swift, Models/UserCreatorChatDisplayMessage.swift, formatter helper와 checker를 함께 컴파일하고 임시 실행 파일을 종료 시 정리한다.

Interfaces:

  • Consumes: Foundation.Locale, Foundation.Calendar, Foundation.TimeZone, Foundation.Date.

  • Produces: enum UserCreatorChatDatePresentation의 static func title(for date: Date, locale: Locale, calendar: Calendar, timeZone: TimeZone) -> String.

  • RED: checker에 Gregorian UTC fixture 2026-10-16T12:00:00Z의 한국어 정확 문자열 2026년 10월 16일 금요일, 영어 full weekday/month/day/year 포함, 일본어 연·월·일·요일 포함 검사를 작성한다. 오늘·어제·이전 연도도 모든 필드 유지, locale과 timeZone 독립성, 전달 calendar의 상이한 timeZone 정규화 검사를 포함한다.

  • RED 확인: sh work/tests/check-user-creator-chat-date-presentation.sh를 실행한다. 최소 컴파일 가능한 임시 구현이 빈 문자열을 반환하도록 두어 한국어 exact-string assertion이 실패함을 확인한다. 컴파일/링크 오류는 의도한 RED가 아니다.

  • GREEN: 위 인터페이스를 구현한다. formatter에 locale, calendar, timeZone을 지정하고 localized template yMMMMdEEEE를 사용한다.

  • GREEN 확인: 같은 sh work/tests/check-user-creator-chat-date-presentation.sh 실행이 exit 0이고 PASS: 뒤에 통과 assertion 수와 assertions가 출력되는지 확인한다.

  • REFACTOR: 이번 Task가 만든 중복만 정리한 후 checker를 다시 실행한다. 불필요한 공유 캐시·언어별 문자열은 만들지 않는다.

Task 1.2 날짜 행과 비고정 UI

Goal P1-T2: 현재 TEXT 표시 메시지로 날짜 구분 행을 파생하고 원래 메시지 목록과 함께 스크롤한다.

  • 시작 조건: P1-T1 완료, DATE-001·005~008 확정.
  • 완료 증거: 행 경계/병합/전송 상태 테스트와 checker 통과, 수동 UI 검증 기록.
  • 범위 밖: 정렬·pagination·ACK 구현 변경 및 비TEXT 표시.

Files:

  • Modify: SodaLive/Sources/V2/Main/Chat/UserCreatorChat/Models/UserCreatorChatDatePresentation.swift (행 파생 계약 추가)
  • Create: SodaLive/Sources/V2/Main/Chat/UserCreatorChat/Components/UserCreatorChatDateSeparatorView.swift (향후 신규)
  • Modify: SodaLive/Sources/V2/Main/Chat/UserCreatorChat/UserCreatorChatRoomView.swift
  • Modify: SodaLive.xcodeproj/project.pbxproj (separator view를 두 앱 타깃 Sources에 등록)
  • Modify: work/tests/UserCreatorChatDatePresentationCheck.swift (행/스냅샷 검사 추가)

Interfaces:

  • Consumes: UserCreatorChatDatePresentation.title(for:locale:calendar:timeZone:), [UserCreatorChatDisplayMessage].

  • Produces: struct UserCreatorChatDatedMessage: Identifiable { let message: UserCreatorChatDisplayMessage; let separatorDate: Date?; var id: String { message.id } } 및 static func rows(from messages: [UserCreatorChatDisplayMessage], calendar: Calendar, timeZone: TimeZone) -> [UserCreatorChatDatedMessage].

  • Produces: UserCreatorChatDateSeparatorView.init(title: String).

  • RED: checker에 빈 목록·단일 행·동일 날짜, 동일/상이 날짜 history prepend 후 첫 날짜 행 이동·중복 없음, VOICE-only 및 혼합 목록의 orphan 없음 검사를 추가한다. Gregorian calendar를 쓰고 서울 2026-10-15T23:30Z→2026-10-16T00:30Z는 구분 1개, 서울 2026-10-16T14:30Z→15:30Z는 2개, LA 2026-11-01T08:30Z→09:30Z는 1개이며 다음 현지 자정에는 추가되는지 검증한다. pending→failed 날짜 유지, pending→server 동일/상이 날짜의 빈 항목 제거·중복 없음, 같은 timestamp의 순서·ID 유지와 기존 pending→server ID 변경도 스냅샷 assertion으로 먼저 작성한다.

  • RED 확인: sh work/tests/check-user-creator-chat-date-presentation.sh를 실행한다. 행 생성의 컴파일 가능한 빈 결과 scaffold에서 단일 표시 메시지의 첫 separatorDate assertion이 실패함을 확인한다.

  • GREEN: rows(from:calendar:timeZone:)는 TEXT 필터 후 순서와 message ID를 유지하며 첫 행과 현지 날짜 변경 행에만 날짜를 설정한다. RoomView는 환경 locale/timeZone 및 정규화 calendar로 행을 파생하고 textMessages projection 및 기존 first/last hook을 보존한다. separator를 VStack(spacing: SodaSpacing.s16)에서 해당 메시지 앞에 표시하며, 중앙 appFont12 regular gray400, 전체 폭, 다중 행, truncation 없음, VoiceOver 날짜 1회 읽기를 제공한다. 기존 메시지 .id(message.id), 첫 메시지 .onAppear -> loadMore, content height preference, viewport auto-fill, 마지막 TEXT id 및 join의 scrollTo(lastMessage.id, .bottom)을 유지하고 날짜 행은 scroll/paging target으로 쓰지 않는다.

  • GREEN 확인: checker 명령이 exit 0이고 RED 단계의 날짜 경계·병합·전송 상태·ID assertion이 모두 통과함을 확인한다. 스냅샷 검증을 실제 소켓 통합 검증으로 주장하지 않는다.

  • REFACTOR: 신규 계산의 중복만 정리하고 checker를 다시 실행한다. 기존 메시지 item, ViewModel, 입력/헤더, 언어 서비스와 DateExtension은 수정하지 않는다.

P1-T2의 UI 증거는 원본 컴포넌트 네이티브 캡처 범위다. 실제 RoomView의 paging·ACK·스크롤 및 VoiceOver 상호작용은 아래 P1-GATE 미완료 항목으로 남긴다.

완료 조건

  • P1-T1, P1-T2의 구현 체크박스와 자동 검사·컴포넌트 렌더링 증거를 기록했다. 전체 사용자 흐름 승인은 Gate와 구분한다.
  • DATE-001~008이 요구사항 추적 표의 Task 및 Gate 증거와 연결된다.
  • SodaLive 및 SodaLive-dev 양쪽 타깃에 필요한 신규 Swift 소스가 포함된다.
  • P1-GATE의 실제 DM 흐름과 VoiceOver QA가 완료됐다.

Phase 1 Gate

Goal P1-GATE: 자동 검사, 두 타깃 빌드와 대화 UI 수동 검증을 종합해 Phase 결과를 판정한다.

  • 시작 조건: P1-T1, P1-T2 완료.
  • 완료 증거: 아래 명령 성공, 수동 QA 기록, 미해결 제한 명시.
  • 범위 밖: 검증을 통과시키기 위한 테스트 완화 또는 관련 없는 코드 수정.
  • TDD 예외 사유: 기존 구현의 검증과 문서 기록만 수행하는 Gate다. 대체 검증 방법: 아래 focused checker, 두 타깃 빌드와 수동 QA 결과를 요구사항별 완료 증거로 남긴다.
sh work/tests/check-user-creator-chat-date-presentation.sh
plutil -lint SodaLive.xcodeproj/project.pbxproj
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build

Expected: checker assertion 전부 PASS, plist lint OK, 두 build 모두 exit code 0. 신규 소스의 양쪽 타깃 멤버십을 확인한다.

수동 검증:

  • 앱 언어 ko/en/ja 및 System, 기기 언어와 앱 locale 불일치에서 앱 언어 표시와 기기 timeZone 날짜 경계가 각각 적용된다.
  • 초기 진입, join, incoming, send, ACK 후 바닥 위치, 첫 메시지 paging, 짧은 viewport auto-fill에서 구분선 높이가 스크롤 흐름을 깨지 않는다.
  • history 로드 전후 스크롤 연속성을 확인한다. 날짜 항목은 함께 스크롤되고 고정되지 않는다.
  • 사용 가능한 서버·테스트 데이터로 실제 전송 중·실패·ACK 후 날짜 변경을 확인한다. 스냅샷 검증과 구분해 기록하며 재현할 수 없으면 관련 QA를 미완료로 유지한다.
  • 좁은 폭, 큰 텍스트 크기, VoiceOver에서 잘림 없이 날짜 전체가 한 번 읽힌다.
  • 구현 완료 후 변경 범위의 코드 리뷰 결과를 docs/sample/sample-review.md에 맞춰 docs/20261016_유저_크리에이터_채팅_날짜_구분선/reviews/phase1-chat-date-separators.md에 기록했다. 코드 범위 APPROVE와 전체 Gate BLOCKED를 구분한다.

요구사항 추적성

요구사항 실행 Task 검증 증거
DATE-001 P1-T2 비어 있지 않은 표시 날짜 행과 UI 표시, Gate 초기 진입
DATE-002 P1-T1, P1-T2 ko/en/ja formatter, 앱 locale 환경 주입 및 불일치 QA
DATE-003 P1-T1, P1-T2 calendar/timeZone 정규화, 서울 경계 및 LA DST 케이스
DATE-004 P1-T1 연·월·일·요일, 오늘·어제·과거 연도 검사
DATE-005 P1-T2 빈/단일/연속 날짜, history prepend 병합 스냅샷
DATE-006 P1-T2, P1-GATE 비고정 component와 스크롤 QA
DATE-007 P1-T2 pending→failed 및 pending→server 날짜 변경/불변 스냅샷
DATE-008 P1-T2 TEXT 필터, VOICE-only 및 혼합 날짜 orphan 검사

실행 순서와 의존성

순서 Goal 선행조건 병행 가능 차단 시 다음 행동
1 P1-T1 사용자 구현 착수 요청 아니요 formatter assertion 또는 빌드 계약 문제를 기록하고 멈춤
2 P1-T2 P1-T1 아니요 행 테스트 실패 원인을 수정 후 같은 Task 검증 재개
3 P1-GATE 두 Task 완료 아니요 실패 소유 Task에 계획된 회귀 수정을 추가한 뒤 재검증
P1-T1 → P1-T2 → P1-GATE

변경 금지와 중단 규칙

  • PRD의 날짜 정책, 사용자 확정 사항, API 계약을 근거 없이 변경하지 않는다.
  • 날짜 sort/dedup, 별도 section state, synthetic ID, DTO, ViewModel 수정, sticky header, VOICE 표시를 추가하지 않는다.
  • 요구 범위 밖 리팩터링, dependency, 테스트 타깃을 만들지 않는다. Pods/**, generated/**, build/**도 수정하지 않는다.
  • 빌드 또는 테스트 오류를 감추기 위해 테스트를 삭제·완화하지 않는다. 소켓 연결 결과를 스냅샷 검증으로 과장하지 않는다.
  • fixture 또는 서버 응답이 필요한 라이브 QA를 사용할 수 없으면 수동 확인을 미완료로 기록한다. 서버/날짜 fixture를 위한 production mock이나 새 재시도 UI를 만들지 않는다.
  • 요구사항과 구현 경계가 충돌하거나 세 번의 서로 다른 수정 시도 뒤에도 차단되면 추가 코드를 작성하지 않고 원인, 관찰 결과, 남은 검증을 기록해 사용자 판단을 기다린다.
  • 리뷰에서 수정 필요가 확정되면 고치기 전에 리뷰 근거와 실행 가능한 회귀 수정 Task를 이 Phase에 추가한다.

Progress

실제 문서 작업과 향후 구현 검증은 구분한다. 아래 체크박스는 미래 실행 항목이다.

문서 작성 실행, 2026-10-16

  • 상태: 계획 작성 완료 / 구현 미착수.
  • 무엇을: 문서 정책, 계획 샘플, 현재 PRD를 읽고 본 계획의 Phase, 요구사항 매핑 및 PRD 링크/범위 결정 기록을 작성했다.
  • 어떻게: docs/agent-guides/documentation-policy.md, docs/sample/sample-plan-task.md, 현재 prd.md, DM View·모델·ViewModel, 앱 locale 주입, 기존 standalone checker와 Xcode 소스 등록 방식을 읽었다. rg로 두 앱 타깃, 최소 iOS 버전과 Swift 버전, XCTest 타깃 부재를 확인했다. 문서 작업 외의 빌드·테스트·앱 실행은 수행하지 않았다.
  • 문서 검증: 두 문서를 다시 읽고 rg -n '^\| DATE-00[1-8]' docs/20261016_유저_크리에이터_채팅_날짜_구분선/plan-task.md의 추적표 8행을 대조해 모든 요구사항이 Task와 검증 증거에 연결됨을 확인했다. 별도 문서 검색에서 미래 구현의 완료 표시·미치환 placeholder·행 끝 공백은 없었다. 두 구현 Task의 RED→GREEN→REFACTOR, Gate 예외 사유, PRD의 상대 링크와 DEC-013도 대조했다.
  • 미실행: sh work/tests/check-user-creator-chat-date-presentation.sh, plutil -lint SodaLive.xcodeproj/project.pbxproj, 두 xcodebuild 명령, 모든 UI 수동 QA. 계획 문서에 기재한 명령은 실행 증거가 아니다.
  • 남은 항목: 모든 구현 체크박스, 코드 및 Gate 검증.
  • 다음 행동: 구현은 별도 사용자 요청이 있을 때만 시작한다.

P1-T1 실행 기록, 2026-10-16

  • 상태: 완료. formatter, standalone checker 및 두 타깃 등록을 commit e765c3c에 기록했다.
  • RED: 컴파일 가능한 빈 문자열 scaffold에서 expected '2026년 10월 16일 금요일', got '', exit 1을 확인했다.
  • GREEN: sh work/tests/check-user-creator-chat-date-presentation.sh를 구현자와 상위 에이전트가 각각 실행해 PASS: 27 assertions, exit 0을 확인했다. plutil -lint SodaLive.xcodeproj/project.pbxproj, git diff --check 통과.
  • 최초 GREEN의 일본어 기대 문자열에는 요일 앞 locale 공백이 누락되어 실패했다. locale 생성 결과를 확인하고 fixture만 교정했으며 필드 검사 요구를 완화하지 않았다.
  • 운영 타깃: xcodebuild -quiet -workspace SodaLive.xcworkspace -scheme SodaLive -configuration Debug -destination 'generic/platform=iOS' -derivedDataPath "$RUN_TMP/standard-build" CODE_SIGNING_ALLOWED=NO build exit 0. 기존 SDK 경고·중복 소스 등록 경고는 범위 밖으로 유지했다. T2 이후 다시 빌드한다.
  • 기존 회귀 기준선: 11개 기존 work/tests 스크립트, 지원 모드 포함 18회 실행 모두 exit 0. DM 화면 변경 후의 완료 증거와는 구분한다.
  • 커밋 검증: 한글 conventional subject 사전 검사와 커밋 직후 work/scripts/check-commit-message-rules.sh 통과. 실제 스크립트는 --message를 지원하지 않아 별도 subject 사전 검사 사용.
  • LSP 도구 없음: Foundation compiler 검사와 앱 빌드 결과를 기록하며 LSP 성공으로 대체 표기하지 않는다.

P1-T2 및 Gate 실행 기록, 2026-10-16

  • 구현: TEXT별 파생 날짜 행, 원본 message ID·순서 보존, 앱 locale·기기 timeZone 연결, 날짜 컴포넌트와 두 타깃 소스 등록을 완료했다. 기존 메시지 시각·ViewModel·API·ACK 로직은 수정하지 않았다.
  • 커밋: 화면 연결·파생 행·직접 회귀 테스트·두 타깃 등록을 7a6d12e로 기록했다. 한글 conventional subject 사전 검사와 커밋 직후 저장소 검사 스크립트가 통과했다.
  • RED: 빈 rows scaffold에서 FAIL: single TEXT message must have its first separatorDate를 확인했다. 이후 sh work/tests/check-user-creator-chat-date-presentation.sh는 PASS: 113 assertions, exit 0. 부모가 최종 소스로 재실행해 동일 결과를 확인했다.
  • 구현 판단: textMessages는 기존 필터를 유지하고 messageListView 내부에서 한 번 캡처해 rows를 계산한다. 계획의 rows→textMessages projection 대신 기존 scroll helper를 유지하는 최소 변경이다. custom caption은 .custom(..., relativeTo: .caption), 영어는 시스템 .caption을 사용해 locale별 Dynamic Type을 지원한다.
  • 전체 빌드가 기존 앱 Font enum과 새 속성 타입 이름의 충돌을 검출했다. SwiftUI.Font로 한 줄 한정한 뒤 동일 명령 두 개가 모두 exit 0으로 통과했다. parse 검사는 이 충돌을 잡지 못했으므로 전체 컴파일 증거와 구별한다.
  • 운영 빌드: xcodebuild -quiet -workspace SodaLive.xcworkspace -scheme SodaLive -configuration Debug -destination 'generic/platform=iOS' -derivedDataPath "$RUN_TMP/standard-build" CODE_SIGNING_ALLOWED=NO build 성공.
  • 개발 빌드: xcodebuild -quiet -workspace SodaLive.xcworkspace -scheme SodaLive-dev -configuration Debug -destination 'generic/platform=iOS Simulator' -derivedDataPath "$RUN_TMP/simulator-build" CODE_SIGNING_ALLOWED=NO build 성공. 최초 전체 의존성 빌드는 600초 timeout 뒤 캐시를 이용해 재개했다.
  • 최종 회귀: 기존 11개 스크립트의 지원 모드 18회와 신규 날짜 검사 1회, 총 19회 모두 exit 0. 기존 테스트 파일은 수정하지 않았다. XCTest 타깃과 공식 lint 명령이 없어 이를 실행했다고 주장하지 않는다.
  • 네이티브 QA: 원본 컴포넌트와 폰트를 임시 앱에서 직접 컴파일해 iPhone SE3/iOS18.3의 ko/en/ja × normal/accessibility3 × light/dark 12장 촬영. 폰트 타입 수정 이후 재촬영하고 production 소스 9개 SHA-256 일치를 확인했다. 캡처는 evidence에 보존한다.
  • 앱 실행: 개발 앱을 소유된 시뮬레이터에 설치·실행해 홈 화면까지 확인했다. 인증된 DM 방은 확인하지 않았고 서버 데이터를 만들거나 개인 인증 정보를 읽지 않았다.
  • 코드 리뷰: Oracle이 코드 범위 APPROVE, 구체적인 잔여 코드 차단 사항 없음으로 판정했다. 최종 Gate는 실제 DM 및 VoiceOver QA 부족으로 BLOCKED다.
  • 최종 시각 재검토: 소스 해시 불일치와 시스템 추적 권한 팝업 가림이 있었던 중간 캡처는 사용하지 않았다. 최종 소스와 팝업 없는 환경으로 12장 재촬영 후 독립 검토자가 12/12 PASS, 잔여 시각 차단 사항 없음으로 판정했다. 이는 컴포넌트 한정 승인이며 전체 DM Gate 승인이 아니다.
  • 남은 항목: 실제 계정·roomId와 날짜가 다른 이력으로 paging·ACK·스크롤·System 언어를 검증하고 VoiceOver 읽기를 확인한다. LSP 도구 부재도 별도로 남긴다.
  • 정리: 최종 증거를 reviews/evidence에 보존하고 소유된 시뮬레이터 shutdown/delete, custom set 빈 목록과 하네스 프로세스 부재, 임시 루트·캐시·작업 메모 제거를 확인했다. 사용자 시뮬레이터·공유 캐시는 유지했다.

Decision Log

날짜 ID 상태 결정 근거 영향
2026-10-16 DEC-PLAN-001 확정 현재 작업은 구현 계획 문서 작성과 PRD 연결 수정만 수행한다. 구현 체크박스는 전부 미완료로 두고 활성 Goal은 두지 않는다. 사용자 명시 범위 및 최신 요청 전체 Phase, PRD DEC-013
2026-10-16 DEC-PLAN-002 에이전트 기술 설계 Foundation formatter와 파생 행을 기존 DM 경계에서 구현하고 별도 XCTest target/dependency를 추가하지 않는다. 기존 소스 확인과 저장소 checker 패턴에 따른 계획 판단, 사용자 별도 기술 승인 아님 P1-T1, P1-T2
2026-10-16 DEC-PLAN-003 구현 판단 separator는 중앙 appFont12 regular gray400, 전체 폭 다중 행, Dynamic Type 및 VoiceOver 지원으로 구현한다. PRD가 위임한 시각 상세, 기존 앱 관례에 따른 계획 기준이며 사용자 확정 픽셀 사양은 아님 P1-T2, P1-GATE

발견된 문제와 제한

ID 상태 관찰 및 영향 처리 계획
LIMIT-001 미검증 Foundation checker는 날짜 계산과 formatter를 검사하지만 SwiftUI 레이아웃, 실제 viewport와 네트워크 ACK를 증명하지 않는다. 빌드와 기기/시뮬레이터 수동 QA를 Gate에서 별도 기록한다.
LIMIT-002 외부 조건 실제 incoming/history/ACK 흐름을 재현할 서버 계정 또는 날짜 fixture가 없을 수 있다. 접근 불가 시 관련 QA를 미완료로 명시하고 production mock은 추가하지 않는다.