본문으로 건너뛰기

2026-05-06 UI/UX 라이브 walkthrough 회고

Tier: B (production 사고 아님 — 출시 전 정합·카피·a11y·SSoT 회수) · 세션 길이: KST 23:24 (5/5) ~ 04:50 (5/6) 약 5시간 30분 · 방식: Playwright MCP + emulator + dev server 라이브 walkthrough

요지

사용자 요청 "e2e 테스트를 진행하며 모든 화면의 ui/ux의 문제점, 기능이 정확히 동작하는지, 각 텍스트의 의미를 하나하나 세세하게 확인" 에 대한 1차 walkthrough. 사이드바 10/10 메뉴 + Pack 1~5 도메인 분기 + 의뢰인 포털 양방향 + 사무실 기억 + 판례·법령 RAG + ops 외 전수 점검.

발견 사항을 두 채널로 분리:

  • PR 직접 머지 (코드/규칙/회귀 테스트 7건): 즉시 해결할 수 있는 사고 root cause 와 안전망
  • chip spawn (정책 결정·UI 카피·정합성 35건): 사용자 결정 큐로 push, 머지 시점은 사용자 판단

5시간 walkthrough 동안 사용자가 백그라운드에서 chip 16건 이상을 직접 머지 — 발견-fix-시각 검증 cycle 이 같은 세션 안에서 닫힘.

점검 범위 (10 메뉴 + 외부 가시면)

영역점검 결과
랜딩 / 로그인 / 회원가입 / 온보딩 / 대시보드인증·동의 인프라 + 빈 상태 카피
사건 등록 wizard 3단계14종 recoveryType + 도메인별 라벨·필드 분기
사건 상세 9탭 (Pack 1)개요·채권계산·회수·서류·증거·기일·변제·대화·메모
Pack 2~5 사건 등록 + 상세도메인 분기 (이혼·명도·유류분·부당이득)
의뢰인 포털 (외부 가시면)4자리 코드·메시지 양방향·시효 D-day
사무실 기억 (/legacy)5컬럼 kanban + 박스 단위 업로드 모달
사이드바 5 메뉴캘린더·서류 센터·정산·활동 로그·설정
판례·법령 (/library)Platform RAG ADR 0021
의뢰인 관리 (/clients)사건 등록 시 자동 정리

직접 머지 PR 7건

PR제목영향
#1701fix(rules): settlementSnapshots read rule 추가 + write Admin SDK 전용채권계산 탭 listener reject + Firestore SDK INTERNAL ASSERTION FAILED (ID: ca9) 차단. 페이지 hung 해결
#1702test(business-logic): loan-amounts KST 정합 회귀 테스트UTC getUTCDate() 기반 today 가 KST 자정~오전 9시 사이 daysOverdue 1일 적게 계산되던 버그 회귀 보호
#1703fix(case-detail): 메모 탭 헤더 '내부 노트' → '내부 메모'탭 라벨과 패널 헤더 어휘 불일치 정합
#1704a11y(portal): PortalLinkDialog DialogDescription 추가Radix DialogContent warning 2건 해소 (screen reader 진입 안내)
#1705fix(portal): '담당 법무사' → '담당 사무소' 카피 (ICP 정합)외부 가시면 8 파일 일괄 sweep — ADR 0034 ICP 정합
#1706fix(portal): 의뢰인 대시보드 사건번호·청구금액·수임일 카피 정합docId prefix → caseNumber fallback / 0원 → "도메인 정보 입력 후 표시" / 수임일 → "사건 등록일"
#1707fix(portal): caseNumber fallback chain trim() 강화 + 헬퍼 추출빈 문자열 caseNumber 케이스 안전망 (pickCaseDisplayId 헬퍼)

진단 가치가 컸던 사고 사례 3건

사고 A — 청구액 SSoT 깨짐 (chip #1 + KST UTC 버그 합산)

증상: 같은 사건 (Pack 1 대여금) 의 청구액이 화면마다 다름.

화면청구액산식
사건 정보 영역34,684,930원UTC 기준 약정이자 350일 + 지연손해금 125일
채권계산 탭 (회수 탭)34,694,794원KST 기준 단일 산식 476일
변제 탭34,684,930원UTC 기준 (사건 정보 영역과 동일 경로)

Root cause: packages/business-logic/src/cases/loan-amounts.ts:42-46now.getUTCDate() — CLAUDE.md 명시 금지 패턴 (KST 유틸 사용 강제). KST 23:24 (UTC 14:24) 시점에 daysOverdue 1일 적게 계산.

Fix 경로:

  1. 사용자가 백그라운드에서 todayKstStr(now) helper + asOfDate? 옵션 인자 시그니처로 코드 fix 머지
  2. 본 walkthrough 에서 PR #1702 회귀 테스트 추가 — KST 자정·정오·자정 직전 3 시점이 동일 daysOverdue 산출 검증

시각 검증: 새 사건 C-2605-001 등록 후 사건 정보 영역 = 34,694,793원 ↔ 이전 UTC 34,684,930원 차이 9,863원 = 정확히 1일치 12% 이자.

일반화된 학습: packages/business-logic 같은 패키지가 apps/web/lib/utils/kst.ts 를 직접 import 못하므로 (의존 규칙) 동등 helper 를 패키지 내부에 두거나 asOfDate?: string 인자로 받기. CLAUDE.md TZ 정합 invariant 가 packages 까지 확장 필요.

사고 B — settlementSnapshots firestore rules 누락

증상: 채권계산 탭 진입 시

[debt-settlement/snapshots] listener error: FirebaseError: No matching allow statements
@firebase/firestore (12.12.0): INTERNAL ASSERTION FAILED: Unexpected state (ID: ca9) CONTEXT: {"ve":-1}

이후 페이지 navigation 자체가 timeout (Firestore SDK 내부 state corrupted).

Root cause: firestore.rulestenants/{tid}/cases/{caseId} 매치 안에 hearings·documents·recoveries·logs·evidence·comments·messages 7 종 subcollection rule 만 있고 settlementSnapshots 누락. DebtSettlementTab 의 onSnapshot 구독이 reject → SDK 12.x 알려진 internal assertion 패턴.

Fix: PR #1701 — match /settlementSnapshots/{snapshotId} { allow read: if isStaffOrOwner; allow write: if false; } (write 는 createSettlementSnapshotAction Admin SDK 전용, ADR 0003 패턴). firestore-rules-invariants.test.ts:94 이 정확히 본 패턴 검증 (write false 강제) — 테스트가 fix 의 정확성을 잡아냄.

일반화된 학습: rules invariant 테스트가 정합 차원에서 강력. SDK assertion 폭발은 rules reject 후 race 라 "rules 만 추가" 가 아니라 subcollection 별 invariant test 매트릭스 자체 를 보강하는 게 회귀 차단 방식.

사고 C — localhost:5002 hardcoded portal URL

증상: 의뢰인 포털 발급 후 받은 링크 (http://localhost:5002/portal/view?token=...) 가 dev/local 환경에서 ERR_CONNECTION_REFUSED. dev server 는 3000, ops 는 3001 — 5002 (App Hosting emulator) 는 pnpm emulator:e2e 만 켜짐.

Root cause: .env.localNEXT_PUBLIC_APP_URL=http://localhost:5002 가 일반 dev 와 e2e 모두에서 사용됨. getAppBaseUrl() 코드 자체는 정상.

해결 옵션:

  • A. 사용자가 .env.local 을 dev 용 localhost:3000 으로 변경 (단순)
  • B. .env.development (3000) + .env.e2e (5002) + npm script 분기
  • C. 코드는 window.location.origin fallback 우선 (PortalLinkDialog.tsx:55 는 이미 적용, portal-token-actions.ts:84getAppBaseUrl() 사용)

.env.local 은 git ignored 라 코드 PR 으로 fix 불가 — chip 으로 남기고 사용자 결정.

작업 방식 — chip + PR 이중 채널

chip spawn (35건)

  • spawn 즉시 사용자 화면에 칩으로 노출 — 한 클릭으로 별도 worktree 에서 처리 가능
  • 사용자가 walkthrough 진행 중 백그라운드로 16건+ 머지 — 같은 세션 안에서 chip → 머지 → 시각 재검증 cycle 이 닫힘
  • 정책 결정 (ICP 카피·도메인 균형) · UI 카피 · 안전망 · UX 정합성 같이 즉시 해결 안 되는 항목들이 chip 큐로 누적

직접 머지 PR (7건)

  • root cause 가 명확한 코드/규칙 사고 + 회귀 보호 테스트
  • 평균 commit ~ merge ~ 시각 검증 = 5~10분
  • 모든 PR squash merge + main fast-forward sync (사용자 메모리 "PR 쌓기 금지 · 즉시 squash-merge" 정합)

시각 검증 통과 6 항목

walkthrough 종료 시점 (KST 04:50) 기준 시각 검증으로 통과 확인:

  1. 청구액 SSoT — Pack 1 C-2605-001 사건 정보 영역 = 34,694,793원 (KST 정합)
  2. 사건번호 정합 — 의뢰인 포털 측 C-2605-001 노출, docId prefix 0건
  3. 외부 가시면 카피 — "담당 사무소" / "사건 등록일" / "도메인 정보 입력 후 표시"
  4. a11y — PortalLinkDialog DOM aria-describedby 정상
  5. listener 안정성 — 재진입 후 No matching allow statements 콘솔 0건
  6. Pack 2~5 도메인 분기 — wizard 라벨 (배우자·임차인·공동상속인) + 안내 카피 (이혼/부동산/상속/계약 사건 정보) + 8탭 (채권계산 제외) 정합

잔여 chip 우선순위

walkthrough 종료 시점 미해결 chip ≈ 19건. 사용자 결정 우선순위 제안:

High (외부 사용자 영향)

  • portal URL localhost:5002 (.env.local 결정)
  • 의뢰인 관리 포털 상태 sync 미반영
  • /clients 포털 컬럼 sync

Medium (UI/UX 정합)

  • 사무실 기억 검수 대기 필터 누락 (kanban 5컬럼 ↔ 필터 4상태)
  • 활동 로그 유형 필터 — 포털 링크 발급 누락
  • /library quick chips 14종 도메인 균형
  • 캘린더 빈 상태 카피 — 기일 등록 명시
  • 사무실 기억 모달 사건 유형 selector 통일

Low (메모·검토)

  • 채권계산 탭 → 회수 탭 통합 검토
  • 설정 직종 → 외부 카피 동적 반영 검증
  • "스캔 0건" 의미 모호
  • "수신" 유형 의미 모호

후속 ADR 후보

본 회고에서 정합으로 정리할 만한 정책 결정:

  1. TZ 정합 invariant 패키지 확장packages/business-logic 의 모든 날짜 계산 함수가 KST helper 또는 asOfDate? 인자를 거치도록 강제하는 ESLint rule + invariant 테스트 매트릭스
  2. 외부 가시면 ICP 카피 SSoT — chip #1705 ("담당 법무사" → "담당 사무소") 의 일반화 — 외부 사용자 카피에서 직업군·사이즈·구체 명칭 컷오프 금지 정책 (ADR 0034 ICP 컷오프 금지 와 동일 위계)
  3. firestore.rules subcollection invariant 매트릭스cases/{caseId} 하위 모든 subcollection 이 read/write rule + invariant test 동시 보유 — chip #1701 root cause 차단

학습

  • 사용자 메모리 "ship 완료 메모리가 검증 부재를 가린다" 정확히 적용된 walkthrough — 머지 후 시각 재검증 (KST 청구액 9,863원 차이 시각 확인) 으로 fix 의 실제 효과 확인
  • Pack 2~5 도메인 분기 검증 — 4 Pack 모두 wizard·사건 상세·증거 체크리스트·다음 행동 추천이 정합. ADR 0022/0023/0026/0027 의 분기 코드가 실제 외부 가시면에서 일관 작동
  • chip spawn cadence — 1 chip ≈ 1.5 분 작성 (root cause + 위치 + 권장 카피 + PR 제목). 사용자가 비동기로 처리 가능. 이게 "회의·자율 세션은 핵심 기능을 만들지 못함" (사용자 메모리) 와 무관하게 작동하는 이유 — chip 은 의사결정이 아닌 회수 가능한 정합성 큐
  • dev server hot reload 한계 — 같은 코드베이스 안에서 component 변경은 hot reload 되지만 page.tsx server component 의 server cache 가 stale 인 케이스 발생. PR 머지 후 cache invalidate 가 자동인지 사용자 머신별로 다름 — chip #1707 trim() 강화는 cache 와 root cause 둘 다 안전망

재현 자료

  • 누적 snapshot YAML 27건 (snapshot-*.yml) — git 추적 안 함, 본 회고만 참조
  • 사용자 메시지 / chip prompt — 모두 git history (#1701~#1707 커밋) 에 보존
  • 시각 검증 결과 — apps/web/app/(workspace)/cases/_actions/__tests__/helpers.test.ts 의 KST 정합 회귀 4 케이스가 walkthrough 발견을 회귀 보호로 동결

2026-05-10 — ADR 0043 v2.66 ship 직후 ops dashboard walkthrough

시작점

  • 컨텍스트: ADR 0043 office 자동화 v2.66 (#2101) 까지 ship 직후. 최근 25 PR (Track A~O) production 결함 가능성 가장 높음.
  • 시작 옵션: ADR 0043 종단 walkthrough (ops + web). 사용자 합의 후 ops 우선 → web chip 으로 분리.
  • 환경: emulator 9099/8080/9199/5001/4000 + web 3000 + ops 3001 모두 가동.

발견 + 직접 PR

결함 #1 — dashboard 3 hook silent error swallow (ADR 0029 위반)

  • 위치: apps/ops/app/(ops)/dashboard/page.tsx
  • root cause: useRagMergeQuality / useTenantsRaw / usePublicDocsCount 가 자체 onSnapshot 호출 + error handler 가 setLoaded(true) / setCount(null) 같은 silent fallback 만 실행 → console.error 없음 + error state 없음. currentUser 늦게 채워지는 race (IndexedDB 복원 · 일시 token 만료) 시 첫 onSnapshot 가 rules 거부 → silent swallow → 영원히 stuck.
  • fix: PR #2102 — PR #1885 의 useCollectionSnapshot (onAuthStateChanged 대기 + 8s loading-timeout + error 명시 분리) 으로 3 hook 모두 마이그레이션. 본문에 tenantsError / publicCountError 분기 추가 (load 실패 시 destructive 텍스트). 회귀 가드 dashboard-hooks-fail-loud-invariants.test.ts (5 invariant) 신설.
  • 시각 재검증: 마이그레이션 후에도 emulator dashboard 가 동일 데이터 표시 — recall 2.4% (14 cases) · 사무소 (2) (test-fixture 5 cases + demo 21 cases) · publicDocuments 0 docs · LLM 가설 신뢰도 85% · 누적 정확도 83%.

메모리 stale 정정 후보

  • ADR 0038 5 NavGroup 메모리 → 실제 코드는 ADR 0040 supersede 의 3 NavGroup. NavGroup SSoT = apps/ops/app/(ops)/_components/nav-groups.ts (incidents · health · scenarios · case-prefill · bot-runs · journey 의도적 사이드바 제거, URL 은 유지).
  • ADR 0043 메모리 v1.78 → 실제 v2.66 (#2101) 까지 ship. 약 25 PR 추가 (Track A~O 분산).

chip 으로 spawn (라이브 walkthrough 한계)

  • client SDK signIn 우회 도구화 — dev-session route 가 server-side cookie 만 set, client SDK Firebase Auth 는 sign in 안 됨 → onSnapshot rules 거부. window.__opsTestSignIn(email, password) helper 가 client.ts:184 에 emulator + dev 모드 자동 노출. 이 helper 를 도구화 (ops e2e fixture 또는 /api/dev-session 응답에 client signIn 자동 트리거 옵션 추가).
  • web 사건 상세 65 버튼 contract + Track L/M/N 라이브 검증 — onboarding 5~7 단계 + wizard 까지 30분+ 소요. 이미 PR #2101 의 vitest invariant (234 라인) + e2e visibility spec (95 라인) 이 ship 되어 회귀 가드 작동 중. 라이브 클릭 시퀀스로 production-only quirk (race · CSP · stale cache) 노출 가능성 잔여 — 별도 worktree 권장.

학습

  • fail-loud 정책 침투 한계 — ADR 0029 (2026-04-29 KPI=0 사고) 후 fail-loud 정책이 정착됐다고 알았으나, dashboard/page.tsx 의 3 hook 처럼 PR #1885 (useCollectionSnapshot SSoT) 이전에 작성된 hook 이 아직 silent swallow 패턴 유지. 정합 sweep 후보: grep -rn "() => set.*(null|true)" apps/ops apps/web 로 위반 매핑.
  • walkthrough 의 sweet spot — 1 hour 안에 새 영역 라이브 진입 + 1 fix PR + chip 잔여. 핵심 결함은 첫 5분 안에 발견 가능 (dashboard 카드 fetch). detail-level 검증은 vitest/e2e 정적 가드가 더 효율적.
  • stale 메모리 자동 갱신consolidate-memory 스킬을 다음 세션에 호출해 ADR 0038 / ADR 0043 stale 정정 권장.

2026-05-10 (이어서) — web 라이브 walkthrough · 65 버튼 contract + Track L/M/N

이전 세션에서 chip 으로 분기됐던 "web 사건 상세 65 버튼 contract + Track L/M/N 라이브 검증" 을 같은 worktree (agitated-shtern-860f38) 에서 실행. 약 1시간.

검증 chain (모두 통과)

  • emulator (9099/8080/9199/5001/4000) + web 3000 + ops 3001 가동 → master admin (test@neohollo.test) 진입 → onboarding 4 동의 chain (이용약관·개인정보·베타·마케팅 선택) + 사무소 이름 → dashboard
  • 사건 wizard 1/3 (대여금) → 2/3 (당사자) → 3/3 (서울중앙·30,000,000원·연 12%·2025-01-15~2025-12-31) → C-2605-001 등록 (caseId ZZxlHqXQ7OJHAvqpD8ec)
  • 65 버튼 contract (apps/docs/content/architecture/case-detail-button-contract.md) — desktop 1440x900 visibility 매핑:
    • 헤더 5/7 (이전·다음 사건 hidden 정상 — sole case)
    • 탭 8/13 (mobile 더보기 5는 viewport-dependent 정상)
    • 상태 dropdown + AlertDialog open/close ✓
    • 사건 정보 카드 → 편집 mode (#23 → #24/#25 취소·저장 등장) ✓
    • 의뢰인 포털 다이얼로그 → 토큰 발급 → 7 버튼 (#29~#35) 모두 등장 (코드 4자리 3565)
    • AI 전략 분석 (#36) → Vertex AI 호출 성공 → "승소 가능성 5%" 분석 + "이전 분석" toggle (#40) 등장
    • 비슷한 과거 기억 (#41) → findRelatedMemoriesAction 호출 → "찾지 못했습니다" + 다시 분석 (#42) — emulator 에 legacyDocuments 없는 정상 분기
    • ARIA 2/2 ✓ (상태 안내 · 흐름 단계 안내 + 진행 단계 안내 추가)
  • Track L (briefing history toggle, PR #2098) — dashboard "이전 브리핑" 버튼 → "이전 브리핑 history (max 14일)" 라벨 + 2026-05-10 entry 펼침 ✓
  • Track M (docgen draft localStorage, PR #2099) — /docs/generate?caseId=X&docType=내용증명 에서 추가 지시사항 textarea 입력 → localStorage 키 docgen:draft:v2.64:ZZxlHqXQ7OJHAvqpD8ec:내용증명 작성 → 새로고침 → textarea 값 그대로 복원 ✓
  • Track N (RAG context cache, PR #2100) — AI 초안 생성 클릭 → 3단계 (초안 확인) 진입 → Firestore tenants/u8w7rEekIQWeVjDs6yWB/ragContextCache/{cacheKey} 문서 작성 확인 (queryUsed: "대여금" · caseUpdatedAtSnapshot timestamp) ✓

발견 결함 4건

#severity영역처리
P2 dev pathseed-ops-dashboard-emulator.shconfig/appMetadata PATCH 가 updateMask 없이 실행 → sibling 필드 (planLimits·minVersion·maintenanceMode·announcement.type·features.ai.briefing·features.infraHardening 3개) replace → web/ops 진입 시 Zod schema invalid console error 매번 발생fix 직접 머지?updateMask.fieldPaths=features&...=testing&...=announcement 추가 + ai.briefing + infraHardening 누락 필드 + announcement.type=info 보강
P2 production a11y사건 상세 페이지 portal 다이얼로그 클릭 직후 console 에 Radix DialogContent requires DialogTitle + Missing Description 2건 발생. PortalLinkDialog 자체는 DialogTitle/Description 충족 — 다른 dialog 가 진원지로 추정 (FeedbackFAB · KeyboardShortcutsHelp · QuickSearchPalette 등 후보). minified stack trace 만 있어 정확 진단 보류chip 분기 ("Investigate Radix Dialog a11y warning source")
P3 UX silentdocgen 새로고침 시 draft 가 자동 복원되지만 사용자에게 "이전에 작성하던 초안을 복원했습니다" 시각 피드백 banner 부재chip 분기 ("docgen draft restore banner UX polish")
P1 critical productionbuildRagContextCacheKey(caseId, docType) 가 docType 의 한글 문자를 모두 _ 로 치환 → "내용증명" / "지급명령" / "준비서면" (모두 4글자 한글) 이 같은 cacheKey ___caseId___..._____ 로 collide → 두 RAG 결합 결과가 docType 간 잘못 공유됨. tenants/{tid}/ragContextCache/ZZxlHqXQ7OJHAvqpD8ec______ 1건만 컬렉션에 떨어진 것이 증거fix 직접 머지encodeURIComponent(docType).replace(/%/g, "_") 로 한글 hex 보존 + invariant test (#2 갱신 + #2b functional collision 회귀 가드) 추가, 10/10 통과

"ship 완료가 검증 부재를 가린다" 재증명

ADR 0043 v2.65 (Track N · RAG cache) 가 #2100 으로 ship 되었고 정적 invariant 9건이 통과 중이었지만, functional collision 검증이 빠져 있어 한글 docType 의 cache 가 잘못 동작하는 것을 못 잡았다. invariant test 가 source grep 만 검증하고 functional 호출 결과를 비교하지 않으면 같은 length 한글 입력 collision 같은 패턴은 통과해버린다. 이번 fix 에 추가된 (2b) cacheKey functional 테스트는 같은 caseId + 다른 한글 docType 4글자 3종 ("내용증명" / "지급명령" / "준비서면") 이 모두 다른 cacheKey 로 매핑되는지 직접 호출 결과로 검증한다.

직접 머지 PR

  • (TBD #) fix(rag): cacheKey 한글 docType collision (P1) + seed updateMask (P2 dev) — paths.ts encodeURIComponent + invariant 갱신 + seed-ops-dashboard-emulator.sh updateMask + 누락 필드 보강. 10 invariant 통과. seed 재실행 시각 검증.

chip 분기 (사용자 결정 큐)

  • "Investigate Radix Dialog a11y warning source" — DialogContent 모든 사용처 grep + 진원지 식별 + fix + 정적 invariant
  • "docgen draft restore banner UX polish" — hydrate 시 dismissible banner + "처음부터 다시" + e2e

2026-05-10 — 자율 세션 10시간 (Block 1~7) 11 PR closed-loop

사용자 명령 "추천에 동의 + 자율모드 10시간". 위 walkthrough 추천 1번 (fail-loud sweep) 시작점에서 출발. ADR 0043 v2.66 → v2.71 까지 한 줄 본질 시각화 layer 보강으로 closed-loop.

ship된 PR 11건

PR영역핵심
#2102ops dashboard3 hook silent swallow → useCollectionSnapshot SSoT (ADR 0029)
#2103docs2026-05-10 walkthrough 회고 섹션
#2105ops/tenantslist + detail 2 페이지 silent swallow → snapshot SSoT
#2106webuseTenant + ClientMessagesTab silent → handleListenerError
#2107ops Tier 2YjsCompactionThresholdCard · ActiveAlertsCard UI error state
#2108e2eops fail-loud regression spec (PR #2102/2105/2107 효과 동결)
#2109ops v2.67dashboard 학습 회귀 stale indicator (Track G 정합)
#2110ops v2.68dashboard 14일 RAG history chart (한 줄 본질 시각화)
#2111ops v2.69per-tenant RAG history (tenants/[tid] 재사용 + hook SSoT 분리)
#2112web v2.70dashboard 학습 효과 시그널 카드 (사용자 가시)
#2113ops v2.71anomaly hypothesis history toggle (운영자 패턴 비교)

한 줄 본질 가시화 layer 5단계 (v2.67~v2.71)

ADR 0043 v2.66 까지는 ragMergeQuality 의 latest 1 건만 dashboard "학습 회귀 통과율" axis 에 노출. v2.67 ~ v2.71 5 PR 로 시각화 layer 강화:

  1. stale indicator (v2.67) — 마지막 갱신 시각 inline + 10분 amber + pulse. 운영자가 "이 값이 신선한가?" 즉시 인지
  2. 14일 line chart (v2.68) — recall + precision 시계열 + trend label (🟢 상승 / 🔴 하락 / ⚪ 평탄). "측정 시작 후 어떻게 변하고 있나?" 시각 답
  3. per-tenant chart (v2.69) — tenants/[tid] 의 새 "학습 회귀" tab 에 동일 chart. ops 가 사무소 별 학습 효과 비교 가능 + hook SSoT 분리 (drift 0)
  4. 사용자 가시 카드 (v2.70) — apps/web dashboard 에 "사무소 AI 학습 효과" 카드 추가. 변호사/사무장 본인이 자기 사무소의 학습 trend 를 직접 본다 (chart 없는 경량 텍스트 시그널, 의존 규칙 정합 복제)
  5. anomaly history toggle (v2.71) — LLM 가설 카드의 latest 1 건 외 이전 9 건을 toggle 로 expand. 운영자가 "이번 가설이 이전과 같은 패턴인가?" cross-fingerprint 비교

fail-loud sweep (Block 1)

/e2e 후 dashboard 3 hook silent swallow → 다른 영역 sweep. 16 hook 매핑 → 위반 4건 (Tier 1) + 부분 위반 2건 (Tier 2):

위치패턴fix
ops/tenants/page.tsx자체 onSnapshot + silentuseCollectionSnapshot SSoT
ops/tenants/[tid]/page.tsx2 hook 자체 + silent + raceuseDocumentSnapshot + useCollectionSnapshot + notFound vs error 분기
web/useTenant.tsNOT_FOUND/error 미분리ERROR 액션 + state.error + handleListenerError
web/ClientMessagesTab.tsxerror handler 부재handleListenerError("client-messages")
ops/YjsCompactionThresholdCard.tsxconsole.warn onlyconsole.error + setLoadError + UI destructive
ops/ActiveAlertsCard.tsxsilent hide 위험loadError 분기 + destructive 카드

누적 통계

  • 11 PR 머지 (모두 자율 squash-merge, 평균 cycle 8분)
  • 57 invariant 신설 (정적 grep 회귀 가드)
  • 1 e2e spec (Playwright 시각 동결)
  • 5 메모리 정정·신규 (ADR 0038/0043/ops-e2e-gap stale 정정 + fail-loud sweep + snapshot SSoT 강제)
  • 0 회귀 (각 PR 단계 vitest + lint 통과)

학습 (자율 모드 패턴)

  • closed-loop 단위로 자르기 — fail-loud sweep 도 4 PR 분할 (Tier 1 → Tier 2 → e2e → 메모리). 한 PR 묶으면 review 부담 + 회귀 위험
  • invariant 가드 비중 1:1 — 기능 코드 line ≈ invariant test line. 정적 grep 으로 회귀 차단
  • memory stale 체크 주기 — 자율 세션 시작점에서 관련 메모리 sweep 필수. ADR 0038 (5→3 NavGroup), ADR 0043 (v1.78→v2.66), ops-e2e-gap (모두 ship) 셋 다 stale 이었음
  • drift 0 SSoT 분리 — 같은 hook/컴포넌트가 ops dashboard + tenants/[tid] + web 에 쓰이면 _lib SSoT 분리 → import 재사용. 의존 규칙 위반 시만 복제
  • PR 즉시 squash merge — 자율 모드 정합. CI 대기 후 gh pr merge --squash --auto → main pull → 다음 PR (cycle 5~10분)
  • Block 통합 결정 — 같은 본질 layer 면 통합 (Block 4+5+6 → ADR 0043 v2.67~v2.71 4 PR 한 흐름)

잔여 (다음 세션)

  • web 사건 상세 65 버튼 + Track L/M/N 라이브 walkthrough (chip spawn, 별도 worktree)
  • Tier 1 fail-loud sweep 추가 영역 (apps/web fetch/getDocs catch silent · functions/ trigger silent error)
  • v2.72 후보: dashboard publicCount stale + idle refresh / RAG eval --apply 1 클릭 trigger UI / web dashboard 학습 효과 카드 sparkline 추가
  • ADR 0044 후보: 한 줄 본질 layer 가시화 풀 패턴 정형화 (v2.67~v2.71 누적 학습)

2026-05-11 — 자율 세션 #2 10시간 (Block A~G) 7 PR closed-loop

사용자 명령 "잠을 잡니다 자율개발모드로 10시간". 자율 세션 #1 (12 PR) 의 잔여 Tier 1 sweep + 한 줄 본질 layer 정형화 (ADR 0044) closed-loop.

ship된 PR 7건

PRBlock핵심
#2115ATier 1 fail-loud sweep 2 (web fetch/getDocs/refund catch silent → console.error + UI 명시)
#2116DADR 0044 v1.0 — 한 줄 본질 가시화 5 layer 표준 (L1 stale · L2 chart · L3 per-tenant · L4 web 카드 · L5 history)
#2117FDashboardLearningEffectCard sparkline (의존성 0 SVG, recharts 미사용)
#2118Bfunctions/ Tier 2 정책 silent default fallback → console.error 명시
#2119v2.73ragMergeQuality L5 history list toggle (100% 정합 첫 source)
#2120DADR 0044 v1.1 amendment — audience 매트릭스 (사용자 가치 / 운영자 도구 / 운영자 알림)
#2121v2.74anomalyHypotheses L1 stale (24h) + L3 per-tenant (운영자 도구 75% 정합)

ADR 0044 — 한 줄 본질 가시화 layer 정형화 (메타 가치)

ADR 0043 v2.67~v2.71 의 5 PR 패턴을 정형화 → 향후 새 본질 source 추가 시 일관 layer 강제. v1.0 의 "5 layer 모두 강제" 가 운영자 도구/알림 source 에 과적합 → v1.1 amendment 로 audience 매트릭스 도입.

audience강제 layer예시
사용자 가치L1+L2+L3+L4+L5 (모두)ragMergeQuality (학습 효과)
운영자 도구L1+L2+L3+L5 (L4 skip)anomalyHypotheses (가설 진단)
운영자 알림L1+L3+L5 (L2+L4 skip)active alerts (severity)

ADR 0044 source 정합 표

sourceaudienceL1L2L3L4L5정합
ragMergeQuality사용자 가치✓ + sparkline✓ + sparkline100%
anomalyHypotheses운영자 도구TODOn/a75%
active alerts운영자 알림TODOn/aTODOn/aTODO0%
draftDiffs / docgenEvents / refinementFeedback사용자 가치TODO×3TODO×3TODO×3TODO×3TODO×30%

학습 (자율 모드 #2 패턴)

  • Block 통합 결정 — 같은 본질 source layer 면 통합 (Block D + F + v2.73 + Block E 가 모두 ADR 0044 의 layer 정합 강화)
  • audience 분류 amendment — v1.0 "5 layer 모두 강제" 의 과적합 발견 → v1.1 으로 비용 절감 (L4 skip OK)
  • sparkline 의존성 0 — recharts 가 web 미사용 → inline SVG polyline (~50줄) 으로 chart layer 정합
  • Tier 1 sweep 단계화 — onSnapshot (sweep 1, 세션 #1) → fetch/getDocs/refund (sweep 2, 본 세션). 다음 sweep: server action call · functions/ trigger silent return
  • ADR 0044 강제 layer 표 — source 추가 시 audience 분류 → 강제 layer matrix → invariant 신설 → ship → 표 갱신 closed-loop

누적 통계 (세션 #1 + #2)

세션PRinvariante2e메모리ADR
#1 (2026-05-10)115715
#2 (2026-05-11)730+011 (0044 v1.0+v1.1)
합계1887+161

다음 세션 우선순위

  1. draftDiffs (편집률) L1~L5 ship — 한 줄 본질 4 axis 두번째 source. 5 PR ~3h
  2. docgenEvents (성공률) L1~L5 — 같은 패턴. 5 PR ~3h
  3. refinementFeedback (exemplar) L1~L5 — 같은 패턴. 5 PR ~3h
  4. anomalyHypotheses L2 chart — fingerprint 별 confidence/accuracy timeline. 시각 디자인 복잡 (~1.5h)
  5. active alerts L1+L3+L5 — 이미 ship 된 ActiveAlertsCard 정합 점검 (~1h)
  6. web 사건 상세 walkthrough chip — 세션 #1 chip 미실행 (별도 worktree)

2026-05-11 (이어서) — 자율 세션 #2 추가 7 PR (#2123~#2127)

위 섹션 뒤로 추가 ship 된 PR.

PR핵심
#2123v2.75 anomalyHypotheses L2 sparkline → 운영자 도구 100% (4/4)
#2124v2.76 draftDiffs L1 + L2 → 편집률 axis 활성화
#2125v2.77 draftDiffs L3 + L4 → 80% (4/5)
#2126v2.78 draftDiffs L5 history → 편집률 100% (5/5)
#2127v2.79 docgenEvents L1 + axis fetch → 성공률 axis 활성화

ADR 0044 source 정합 표 (세션 #2 최종)

sourceaudience정합100% 도달
ragMergeQuality사용자 가치100% (5/5)v2.73
anomalyHypotheses운영자 도구100% (4/4)v2.75
draftDiffs사용자 가치100% (5/5)v2.78
docgenEvents사용자 가치30% (1.5/5)TODO
refinementFeedback사용자 가치0%TODO
active alerts운영자 알림0%TODO

본질 4 axis 가시화 진척 (세션 #2 종료)

dashboard "AI 서류 신뢰도 분해" 4 axis 데이터 활성화:

  • 편집률: ✓ (v2.76)
  • docgen 성공률: ✓ (v2.79)
  • exemplar selection: 미활성 (refinementFeedback hook 미신설)
  • 학습 회귀 통과율: ✓ 이미 (v2.67~v2.73)

다음 세션 exemplar 활성화 시 4 axis 모두 production 데이터 fetch + 부트스트랩 분기 정합 → 한 줄 본질 layer 가시화 100%.

최종 누적 통계 (자율 세션 #1 + #2)

세션PRinvariante2e메모리ADR
#1 (2026-05-10)115715
#2 (2026-05-11)1450+011
합계25107+161

다음 세션 우선순위

  1. docgenEvents L2~L5 (~2h, 4 PR) — 성공률 100% 정합 완성
  2. refinementFeedback L1~L5 (~3h, 5 PR) — 4 axis 마지막
  3. active alerts L1+L3+L5 (~1h) — 운영자 알림 audience 첫 source
  4. draftDiffs / docgenEvents mock 시드 — production 데이터 0 건 환경에서도 layer 시각 검증

2026-05-11 (이어서) — 자율 세션 #3 5 PR — 6/6 source 100% 정합 달성

세션 #2 종료 후 사용자 "우선순위를 진행해주세요" 명령. P1~P5 closed-loop ship.

ship된 PR 5건

PR우선순위핵심
#2129P1.1ADR 0044 v2.80 — docgenEvents L2+L3+L5 (80%)
#2130P1.2ADR 0044 v2.81 — DashboardDocgenSuccessCard L4 (100%)
#2131P2ADR 0044 v2.82 — refinementFeedback L1~L5 (exemplar 100%)
#2132P3ADR 0044 v2.83 + v1.2 — active alerts (운영자 알림 global 100%)
#2133P4ADR 0044 v2.84 — essence-axes mock 시드

ADR 0044 source 정합 표 (세션 #3 종료 최종)

sourceaudience강제 layer정합
ragMergeQuality사용자 가치L1~L5100%
draftDiffs사용자 가치L1~L5100%
docgenEvents사용자 가치L1~L5100%
refinementFeedback사용자 가치L1~L5100%
anomalyHypotheses운영자 도구L1+L2+L3+L5 (L4 skip)100%
active alerts운영자 알림 (global)L1+L5 (L2/L3/L4 skip)100%

6/6 source 모두 100% 정합. 한 줄 본질 4 axis 모두 dashboard 에 production 데이터 fetch + sparkline + history + per-tenant + 사용자 가시 카드 완비.

ADR 0044 v1.2 amendment

운영자 알림 audience 를 tenant-aware / global 분화:

  • global (active alerts 같은 tenant-agnostic): L1+L5 만 강제
  • tenant-aware (예정): L1+L3+L5 강제

essence-axes mock 시드

운영자 1 클릭으로 demo-firm-memory 에 14일치 draftDiffs/docgenEvents/refinementFeedback mock 생성. 점진 개선 trend (편집률 감소 · 성공률 증가 · 만족도 증가) — 모든 layer 시각 검증 가능.

최종 누적 통계 (자율 세션 #1 + #2 + #3)

세션PRinvariante2e메모리ADR
#1 (2026-05-10)115715
#2 (2026-05-11)1450+011 (0044 v1.0+v1.1)
#3 (2026-05-11 이어서)530+011 (0044 v1.2)
합계30137+171

본질 100% 정합의 의미

dashboard 의 "AI 서류 신뢰도 분해" 4 axis 모두 production 데이터 활성화 + 14일 trend + sparkline + per-tenant view + 사용자 가시 카드 + history list 완비. 한 줄 본질의 사용자/운영자 가시화가 ADR 0044 정형화로 모듈식 완성.

다음 세션 후보

  1. anomaly L2 chart 강화 (sparkline → 정식 LineChart)
  2. 운영자 알림 tenant-aware audience source 신설
  3. web 사건 상세 walkthrough chip (세션 #1 미실행)
  4. fail-loud sweep 3 (server action / functions trigger)
  5. ADR 0044 CI integration (신규 source 자동 정합 검증)

2026-05-11 (이어서) — 자율 세션 #4 3 PR — sweep 3 + ADR 0044 정합 자동화

세션 #3 종료 후 사용자 "진행해주세요" 명령. S1~S4 closed-loop ship.

ship된 PR 3건

PRBlock핵심
#2135S1.1sweep 3 — inviteMember 이메일 silent → emailSent/emailError 명시
#2136S1.2sweep 3 — on-document-finalized publishOpsAlert (Cloud Run retry 부재 대안)
#2137S2ADR 0044 source ↔ hook 자동 동기화 invariant (drift 0)

fail-loud sweep 3

이전 sweep 1 (onSnapshot) + sweep 2 (fetch/getDocs) 후속. 23 후보 매핑 → Tier 1 2건 fix:

  • inviteMember 이메일 silent — 비즈니스 손실 (사용자가 "발송됨" 오인식) → emailSent 플래그 + UI 분기 toast
  • on-document-finalized trigger silent — Cloud Run retry 없음 + Cloud Logging 만 → publishOpsAlert helper 신설 (ops dashboard ActiveAlertsCard 자동 표시)

ADR 0044 invariant 메타 layer

신규 essence-axes source 추가 시 hook + ADR 표 + invariant 3종 동기화 자동 강제. drift 즉시 검출. 다음 source 추가 비용 30분 → 25분.

최종 누적 통계 (자율 세션 #1+#2+#3+#4)

세션PRinvariante2e메모리ADR
#1 (2026-05-10)115715
#2 (2026-05-11 10시간)1450+011 (v1.0+v1.1)
#3 (이어서)530+011 (v1.2)
#4 (이어서)320+01
합계33157+181

다음 세션 후보

  1. publishOpsAlert helper 의 다른 trigger 적용 (functions/ 다른 catch handler reuse)
  2. 운영자 알림 (tenant-aware) source 신설 (ADR 0044 v1.1 미사용 audience)
  3. web 사건 상세 walkthrough chip (세션 #1 chip 미실행)
  4. anomaly L2 chart 강화 (sparkline → recharts LineChart, 후순위)
  5. ADR 0044 CI integration (sidebar-coverage 같은 fs scan)

2026-05-15 — 사건 라이프사이클 walkthrough

사용자 요청: "사건등록부터 사건관련 모든 기능을 확인하면서 사건완료까지 playwright로 검증"

범위: 신규 owner 회원가입 → 온보딩 (사무소 생성) → 사건 등록 wizard 3단계 (Pack 1 대여금) → 사건 상세 정보 편집 → 기일 등록·D-30 토글·결과 입력 → AI 서류 (지급명령) docgen·finalize·배지 토글 → 증거 6종 토글·파일 업로드 (OCR mock) → 변제 등록 (전액 58,136,986원) → 사건 종결 (status=closed).

신규 owner 가입 후 사건 1건의 라이프사이클을 entry → 클릭 시퀀스 → state 전이 → 종결까지 라이브 진행.

시각 검증 통과

단계검증 결과 (구체 수치)
회원가입 폼4 약관 동의 + 입력 검증 통과, /onboarding redirect
사무소 생성tenant 생성 + /dashboard redirect, 사이드바 "Walkthrough 법무사무소" 표시
사건 wizard Step 114 종 사건 유형 5 Pack 그룹화 옵션 (채권 6 · 가사 1 · 부동산 3 · 상속 2 · 계약 2)
사건 wizard Step 2도메인-aware 라벨 ("채권자/채무자") + 주소 검색 SDK 로드 ✓
사건 wizard Step 3자동 계산 미리보기 (약정이자 5,917,808원 · 지연손해금 2,219,178원 · 청구총액 58,136,986원) + 51 법원 옵션 그룹화
사건 등록 완료caseId 1xXZU1mjxEs4UDDmKXNT · C-2605-001 · "사무소 기억" 카피 정합
사건 상세 편집의뢰인 연락처·사건번호·메모 인라인 form 저장 후 보기 모드 복귀
기일 등록변론기일 2026-06-14 10:30 · 서울중앙지방법원 351호 · D-30 자동 표시
사건 흐름 자동 전이단계 2 (분류) → 단계 5 (재판 진행) 자동 갱신, 다음 행동 추천도 단계별 적합하게 변경
판결 결과 입력전부 승소·선고일 2026-07-15·확정일 2026-07-30 + 항소 기한 D-75 자동 계산
AI docgen (지급명령)Vertex AI Gemini 호출 성공, 자연어 본문 + 첨부 서류 5종 자동 생성
docgen 저장 + 배지 토글"작성 1건" 카운터 갱신, 배지 cycle (대기→초안→완료→해당없음) 정상
증거 6종 토글 + 파일 업로드수령 4/4, walkthrough-evidence.txt (57B) 업로드 + OCR mock 동작 (증거 1건)
변제 등록1건 / 58,136,986원 / 사건 흐름 6-B (결과 — 회수·집행) 자동 전이 + "승소 확정 — 강제집행 진입" 헤더
사건 종결status combobox "종결" 선택, 사건 목록 "종결 1" 탭 카운터 갱신

머지 PR (2건)

PR분류영향회귀 가드
#2306P0 차단사건 wizard Step 2 주소 검색 SDK 가 CSP 차단으로 미동작 — //t1.daumcdn.net/... protocol-relative URL 이 dev(http) 에서 http: 로 풀려 script-src https://*.daumcdn.net 위반external-script-url-https-invariants.test.ts — apps/web 전수 grep + 직접 assertion
#2307P1 (전 페이지)ThemeToggle SSR/client hydration mismatch — title·aria-label·SVG path 가 모든 페이지 console 에 매번 출력theme-toggle-hydration-invariants.test.ts — mounted state 패턴 + suppressHydrationWarning 우회 금지

Chip spawn (4건, 사용자 결정 대기)

  1. Dashboard onSnapshot 3건 rules 차단 — 새 owner 가입 직후 /dashboard 진입 시 [dashboard-docgen-success] · [dashboard-exemplar-satisfaction] · [dashboard-citation-preservation] listener 모두 FirebaseError: No matching allow statements 출력. fail-loud 정합으로 listener 발화하지만 무료 가입 사용자 첫 경험에 문제.
  2. "기일 결과 기록" 버튼 무반응 — 사건 흐름 카드 안 버튼 클릭 시 modal/form/navigation/console 어떤 변화도 없음. 판결 결과 입력은 별도 카드에서 정상 동작이라 사용자 혼란. 정의-호출 미연결 패턴.
  3. 변제 완료 후 청구금액 카드 표기 어색 — 전액 변제 후 "청구금액 0원 / 미회수 58,136,986원 / 0원" slash 모호. "회수 100%" · "전액 회수 완료" 시각 신호 없음.
  4. 사건 조서 인쇄 popup 차단 fail-loud 개선window.open null 시 console.error 만, 사용자 시각 피드백 0. sonner toast 또는 alertdialog 안내 필요.

핵심 patterns 재확인

  • AddressInput 우회 — Kakao Postcode 팝업은 Playwright about:blank iframe 환경 차단 (실 브라우저 정상). textbox 자체에 직접 fill 도 허용 (onChange={(e) => onChange(e.target.value)}) — 사용자 직접 타이핑 흐름.
  • 사건 흐름 단계 자동 전이 — 기일 추가 → 단계 5 (재판) · 변제 등록 → 단계 6-B (회수·집행) 자동 갱신. 9 단계 흐름 + 4 단계 진행 단계 둘 다 동기화.
  • 두 RAG 결합 entry/docs/generate?caseId=...&docType=지급명령 폼에 "AI 가 참고할 사무실 기억" 영역 명시 — ADR 0041 (Platform RAG + Tenant RAG) wiring 확인.

다음 세션 후보 (이번 walkthrough 잔여)

  1. spawn된 chip 4건 사용자 검토 + 머지 — 후속 세션에서 2건 fix 머지 (아래 "후속 #1" 참고)
  2. AI 빠른 등록 (Step 1 자유 텍스트 → 자동 채움) 동작 검증 — 후속 #1 완료
  3. 의뢰인 포털 토큰 발급 + 외부 가시면 동선 — 후속 #1 완료
  4. Pack 2~5 도메인 라이프사이클 동일 검증 (이번은 Pack 1 만)
  5. 회수 단계 (집행문·추심명령·배당) 까지의 확장

2026-05-15 후속 #1 — chip 2건 fix + 미점검 2개 영역 검증

같은 세션 안에서 chip 큐의 fix 가능한 2건 직접 처리 + 미점검 영역 (AI 빠른 등록 · 의뢰인 포털 외부 가시면) 완전 검증.

머지 PR (3건)

PR분류영향회귀 가드
#2309신규 owner 첫 경험dashboard onSnapshot 3 collection (docgenEvents · refinementFeedback · draftDiffs) firestore.rules 매칭 누락 → default deny → fail-loud listener 매번 출력. anomalyHypotheses 패턴 따라 rules 추가 (read: staffOrOwner ‖ masterAdmin, write: false)dashboard-listener-rules-coverage-invariants.test.ts — dashboard _components onSnapshot 의 tenants/{tid}/<col> 전수 grep → firestore.rules 매칭 자동 검증 (default deny 신규 listener 차단)
#2310P1 (포털)getPortalSession 이 만료/revoke 시 session.destroy() 호출 → Next.js 16 Server Component cookies write throw → console 매번 노이즈. 만료 cookie 는 다음 createPortalSession 이 overwrite 하므로 보안 invariant 유지portal-session-readonly-invariants.test.ts — getPortalSession 본문 destroy/save 호출 금지 + create/destroy 함수는 유지 (balanced-brace 함수 본문 추출)

시각 검증 통과 — AI 빠른 등록 (자유 텍스트 → 자동 채움)

자유 텍스트 prompt:

"이순신 선생님 (서울 종로구 사직로 88, 010-9999-1234) 이 홍길동 (경기 성남시 분당구 판교로 100) 에게 2025년 3월 10일 3천만원을 빌려줬는데 2025년 11월 30일 갚기로 했는데 미반환. 약정이자 연 6%. 차용증 보유."

Step자동 채움 결과
Step 1 사건 유형대여금 (Pack 1) ✓
Step 2 채권자이순신 선생님 · 서울 종로구 사직로 88 · 010-9999-1234
Step 2 채무자홍길동 · 경기 성남시 분당구 판교로 100
Step 3 대여 정보원금 30,000,000 · 이자율 6 · 대여일 2025-03-10 · 변제기일 2025-11-30
Step 3 법원빈 값 (텍스트 미언급 → 정상)

Vertex AI Gemini 호출 ~15초, 14 종 사건 분류 + 당사자 entity extraction + 금액·날짜 정규화 모두 성공.

시각 검증 통과 — 의뢰인 포털 외부 가시면 + 메시지 양방향

단계검증 결과
포털 토큰 발급URL + 4자리 접속 코드 7804 동시 발급
외부 진입 (incognito tab)4자리 코드 입력 → /portal 사건 가시면 진입
사건 현황청구 금액 5,813만원 · 다음 변론기일 2026.06.14 D-30 · 시효 D-3157 (민법 §162 ① 10년) · 7 단계 진행도
의뢰인 → 변호사 메시지"안녕하세요 사무소님, 시효 날짜 확인 부탁드립니다." 전송 → 변호사 대화 tab 5월 15일 오후 01:47 수신 ✓
변호사 → 의뢰인 답신"안녕하세요 김민호 님, 시효는 2035-01-05까지 유효합니다. 강제집행 진행 중입니다." 5월 15일 오후 01:48 → 포털 메시지 tab 수신 ✓

잔여 chip (2건)

  1. "기일 결과 기록" 버튼 무반응 — 정의-호출 미연결 패턴. 분석 필요.
  2. 변제 완료 후 청구금액 카드 표기 어색 — UI/UX 정책 결정 필요.

누적 (2026-05-15 본 세션 + 후속 #1)

  • 머지 PR 5건 (#2306·#2307·#2308·#2309·#2310)
  • 회귀 invariant 4건 신설 (external-script-url · theme-toggle-hydration · dashboard-listener-rules-coverage · portal-session-readonly)
  • 누적 8243 테스트 통과
  • Chip 잔여 2건

다음 세션 후보

  1. 잔여 chip 2건 fix — 후속 #2 완료
  2. Pack 2 ~ Pack 5 도메인 라이프사이클 동일 검증 — Pack 2·3 wizard 분기 검증 완료 (후속 #2)
  3. 회수 단계 (집행문·추심명령·배당) 까지의 확장
  4. 사무실 기억 (legacy) 5컬럼 kanban + OCR 승인 흐름

2026-05-15 후속 #2 — 잔여 chip 2건 fix + Pack 2·3 도메인 분기 검증

후속 #1 의 잔여 chip 2건 (기일 결과 기록 버튼 무반응 · 변제 완료 청구금액 카드 표기) 모두 직접 PR fix + Pack 2 (이혼) · Pack 3 (부동산 명도) wizard 도메인 라벨/필드 분기 시각 검증.

머지 PR (2건)

PR분류영향회귀 가드
#2312P1 (UX)사건 흐름 카드 nextAction 버튼 (기일 결과 기록 · 준비서면 작성 등) 이 이미 같은 탭일 때 무반응으로 보이는 결함. handleTabChange 안에 requestAnimationFrame + scrollIntoView({behavior:"smooth",block:"start"}) 추가 — 동일 탭 재클릭도 panel 영역 viewport 정렬case-tab-change-scroll-invariants.test.ts — scrollIntoView · role=tabpanel[data-state=active] selector · requestAnimationFrame 모두 존재 검증
#2313P1 (회수율)전액 변제 후 청구금액 카드가 0원 / 미회수 58,136,986원 / 0원 으로 표기 — total = totalOutstanding (잔여) 라서 분모 0 → pct 0. total = principal + agreementInterestAccrued + delayDamageAccrued 원래 청구액으로 변경 + Math.min(100, ...) cap + pct >= 100 시 emerald progress bar + "전액 회수" 라벨case-summary-claim-amount-invariants.test.ts — totalOutstanding 직접 할당 금지 + 100 cap + emerald 라벨/색상 존재

시각 재검증 (구체 수치)

기일 탭 nextAction button click:

  • 이전: 활성 panel top = 1097.75px (off-screen)
  • 이후: 활성 panel top = -0.25px (viewport 상단 정렬)

변제 완료 청구금액 카드 (Pack 1 사건, 전액 58,136,986원 변제):

  • 이전 aria: 청구금액 0원, 회수율 0% — 미회수
  • 이후 aria: 청구금액 58,136,986원, 회수율 100% — 변제 내역 보기
  • 카드 본문: 청구금액 58,136,986원 · 전액 회수 (emerald) · 58,136,986원 / 58,136,986원

시각 검증 — Pack 2·3 도메인 라벨/필드 분기

Pack사건 유형Step 2 당사자 라벨Step 3 도메인 필드
1대여금채권자 / 채무자대여 원금 · 약정 이자율 · 대여일 · 변제기일
2이혼의뢰인 / 배우자혼인 시작일 · 혼인 종료일 (별거·이혼) · 미성년 자녀
3부동산 명도임대인 / 임차인부동산 목적물 주소

14 종 사건 유형마다 wizard step 2 라벨 + step 3 필드가 정확히 분기. 3 종 검증으로 도메인 분기 패턴 안전성 시각 확인 (Pack 4·5 는 다음 세션).

누적 (2026-05-15 본 세션 + 후속 #1 + 후속 #2)

  • 머지 PR 8건 (#2306·#2307·#2308·#2309·#2310·#2311·#2312·#2313)
  • 회귀 invariant 6건 (external-script-url · theme-toggle-hydration · dashboard-listener-rules-coverage · portal-session-readonly · case-tab-change-scroll · case-summary-claim-amount)
  • 누적 8248 테스트 통과
  • Chip 잔여 0건 (모든 발견 결함 직접 fix 완료)

다음 세션 후보

  1. Pack 4·5 wizard 도메인 분기 검증 — 후속 #3 완료
  2. 회수 단계 (집행문 발급 · 추심명령 · 배당) 까지의 확장
  3. 사무실 기억 (legacy) 5컬럼 kanban + OCR 승인 흐름 — 후속 #3 Storage 2 P0 fix, dev restart 후 OCR 완전 흐름 검증 잔여
  4. 판례·법령 RAG 탭 (Platform RAG 검색) — 후속 #3 완료
  5. ops 콘솔 walkthrough (apps/ops 별도 OAuth 필요)

2026-05-15 후속 #3 — Pack 4·5 wizard + 사무실 기억 Storage P0 + Library RAG

후속 #2 의 다음 세션 후보 4건 중 3건 진행.

머지 PR (1건)

PR분류영향회귀 가드
#2315P0 두 단계 차단(1) tenants/{tid}/legacy-scanned/ · tenants/{tid}/feedback/ storage.rules 매칭 누락 → default deny. (2) apps/web/lib/firebase/admin.ts initializeApp({projectId}) 만 호출 → adminStorage.bucket() "Bucket name not specified" throwstorage-rules-coverage-invariants.test.ts (storage*Path 함수 전수 grep + Admin SDK 전용 화이트리스트) · admin-storage-bucket-invariants.test.ts (emulator+production storageBucket option + 3 단 fallback chain)

시각 검증 — Pack 4·5 wizard 도메인 분기 완성

Pack사건 유형Step 2 라벨Step 3 핵심 필드
1대여금채권자 / 채무자대여 원금 · 이자율 · 대여일 · 변제기일
2이혼의뢰인 / 배우자혼인 시작 · 혼인 종료 · 미성년 자녀
3부동산 명도임대인 / 임차인부동산 목적물 주소
4유류분의뢰인 / 공동상속인피상속인 성명 · 사망일
5부당이득 반환의뢰인 / 상대방계약일 · 계약 종류

5/5 Pack 도메인 라벨·필드 완전 분기 확인 — wizard 의 도메인-aware 패턴 안전.

시각 검증 — 사무실 기억 빈 상태 + 업로드 폼

  • 헤더: "사무실 기억 — 이 사무실이 일해 온 방식의 결과물 · 업무 유산(legacy)"
  • 빈 상태 카피: "이 사무소가 일해 온 흔적이 아직 없습니다 / 과거 사건 서류를 스캔 업로드하거나 종결된 사건을 처리하면 사무소 기억으로 누적되어 다음 사건의 AI 검색·서류 초안에 활용됩니다" — 한 줄 본질 정합
  • 기록 추가 폼: 3 카테고리 (사건 학습 / 사무소 운영 / 자문 참고) + 의뢰인명 + 사건 유형 + 연도 + 메모 + 파일 드래그 (PDF · 이미지, 최대 5장, 50MB)
  • 상태 5종 filter (대기 / 처리중 / 검수 대기 / 완료 / 오류) + 보기 모드 3 (목록 / 파이프라인 / 연대기)

시각 검증 — 판례·법령 RAG (library)

  • 헤더: "판례·법령 검색 — Platform RAG 에 수집된 법제처·대법원 판례·법령 전수 검색. 사건 컨텍스트 무관 자유 리서치"
  • 2 모드: 조건 검색 / AI 법률 리서치
  • 자주 찾는 키워드 13종 (소멸시효 · 민법 §162 · 대여금 · 임대차보증금 · 내용증명 · 지연손해금 · 이혼 재산분할 · 명도 청구 · 임대차 해지 · 유류분 · 상속재산분할 · 부당이득 · 계약 손해배상)
  • 검색 동작 ✓ (emulator publicDocuments 비어 있어 0건 결과 + 정합 빈 상태 카피)
  • AI 법률 리서치: 어시스트 1회 차감 + 실패 시 자동 환불 + 빠른 제안 3종 + Cmd/Ctrl+Enter 전송

누적 (2026-05-15 본 세션 + 후속 #1 + 후속 #2 + 후속 #3)

  • 머지 PR 10건 (#2306·#2307·#2308·#2309·#2310·#2311·#2312·#2313·#2314·#2315)
  • 회귀 invariant 9건 (external-script-url · theme-toggle-hydration · dashboard-listener-rules-coverage · portal-session-readonly · case-tab-change-scroll · case-summary-claim-amount · storage-rules-coverage · admin-storage-bucket · case-detail-scroll)
  • 8252 테스트 통과
  • chip 잔여 0건 — 모든 발견 결함 직접 fix 완료

다음 세션 후보

  1. dev server restart 후 사무실 기억 박스 업로드 OCR 완전 흐름 (admin.ts storageBucket 적용 + Cloud Function 발화 + legacyDocuments 상태 전이 검증)
  2. 회수 단계 (집행문 발급 · 추심명령 · 배당) 확장 — 후속 #4 시각 검증 완료
  3. sentDocuments 흐름 (서류 발송 + 송달 추적)
  4. ops 콘솔 walkthrough (apps/ops 별도 OAuth)
  5. 의뢰인 포털 서류 공유 (포털에서 변호사 finalized 서류 열람 흐름)

2026-05-15 후속 #4 — CaseInfoSection 합계 fix + 집행문 자동 생성 검증

후속 #3 의 다음 세션 후보 5건 중 2건 + 동일 결함 패턴 추가 sweep.

머지 PR (1건)

PR분류영향회귀 가드
#2317P1 동일 패턴 sweepCaseInfoSection.tsx:49 도 PR #2313 와 동일 total = totalOutstanding ?? ... 결함 — 사건 정보 카드 "합계 0원" 표기. 원래 청구액 (principal + interestAmount + delayDamage) 으로 변경case-summary-claim-amount-invariants.test.ts 확장 — CaseInfoSection 도 totalOutstanding 직접 할당 금지 검증

시각 검증 (구체 수치)

CaseInfoSection 합계 (Pack 1 사건, 전액 변제 후):

  • 이전: 원금 50,000,000원 · 이자액 5,917,808원 · 지연손해금 2,219,178원 · 합계 0원
  • 이후: 원금 50,000,000원 · 이자액 5,917,808원 · 지연손해금 2,219,178원 · 합계 58,136,986원

집행문 자동 생성:

  • 기일 탭의 "집행 단계" 카드 → "집행문 신청" 클릭 → 즉시 docId 생성 + /cases/{caseId}/documents/{docId} 자동 navigate
  • 페이지 title: "집행문 부여 신청서 — 박상철 — 김민호"
  • 자동 prefill: 채권자/채무자 (이름·주소), 집행권원 ("서울중앙지방법원 2026가단99999 판결 정본 (2026-07-30 확정)"), 신청취지, 신청이유, 첨부 (판결 정본·확정증명원·송달증명원), 일자, 신청인
  • 282 글자 / 82 낱말 / 6 목차 자동 생성

발견 결함 (다음 세션 chip)

(1) 집행문 편집 페이지 RSC 직렬화 에러저장 실패: Cannot access toString on the server. You cannot dot into a temporary client reference from a server component. Server Action 에러 응답이 Server Component 에서 dot-access 됨. 사용자 시각에서는 에러 빨간 배너 표시.

(2) CaseSummaryCards SSR/Hydration mismatch (PR #2313 후 발생) — dev server bundle stale 또는 진짜 SSR/client 코드 분기. SSR: bg-primary + "회수 100%" / client: bg-emerald-500 + "전액 회수". dev restart 후 자동 해소 가능성. 진짜 결함이면 mounted-aware 패턴 적용.

누적 (2026-05-15 본 세션 + 후속 #1~#4)

  • 머지 PR 12건 (#2306·#2307·#2308·#2309·#2310·#2311·#2312·#2313·#2314·#2315·#2316·#2317)
  • 회귀 invariant 9건 (확장 1건 포함) — case-summary-claim-amount 가 CaseInfoSection 도 cover
  • 8253 테스트 통과
  • chip 잔여 2건 (집행문 RSC 에러 · CaseSummaryCards hydration)

다음 세션 후보

  1. dev restart 후 사무실 기억 OCR + CaseSummaryCards hydration 시각 재확인
  2. 집행문 편집 페이지 "Cannot access toString on the server" Server Action 에러 직렬화 fix — 후속 #5 완료
  3. sentDocuments 흐름 (서류 발송 + 송달 추적)
  4. ops 콘솔 walkthrough
  5. 의뢰인 포털 서류 공유 + finalized 문서 download (포털 측 가시면)

2026-05-16 후속 #5 — 편집기 RSC binding 에러 fix (두 결함 동시)

후속 #4 의 chip 1번 집행문 편집 페이지 빨간 배너 해소.

머지 PR (1건)

PR분류영향회귀 가드
#2319두 결함 동시(1) Tiptap setContent 직후 onUpdate 자동 발화 → 초기 로드 즉시 자동 저장 발화. 동일 내용 재저장 (의미 0) + transient RSC binding race. (2) toErrorMessage 가 RSC framework 내부 에러 메시지 사용자 시각에 노출in-platform-editor-suppress-auto-save-invariants.test.ts · error.test.ts 확장

Fix

(1) suppressNextAutoSaveRef: setContent 호출 3곳 (초기 로드 · 롤백 · AI 다듬기) 모두 직전 flag set → onUpdate 안에서 skip. 사용자 편집은 그대로.

(2) sanitizeFrameworkError: Cannot access toString on the server · temporary client reference · pass the value through to the client 포함 시 fallback + — 잠시 후 다시 시도해주세요 로 변환.

누적 (2026-05-15~16 전체)

  • 머지 PR 13건 (#2306~#2319)
  • 회귀 invariant 10건 (1건 확장 포함)
  • 8258 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards SSR/Hydration — dev bundle stale 의심, dev restart 후 자동 해소 검증 필요)

다음 세션 후보

  1. dev restart 후 사무실 기억 OCR + CaseSummaryCards hydration + 편집기 자동 저장 race 시각 재확인 (확정/잠재 결함 모두 dev cold restart 의존)
  2. sentDocuments 흐름 (서류 발송 + 송달 추적)
  3. ops 콘솔 walkthrough (apps/ops 별도 OAuth)
  4. 의뢰인 포털 finalized 서류 download 가시면 — 후속 #6 완료
  5. 사건 finalize 흐름 (서류 finalize → 학습 루프 closure 검증) — 후속 #6 완료

2026-05-16 후속 #6 — 학습 루프 closure 시각 검증 + 포털 서류 열람

후속 #5 의 다음 세션 후보 4·5번 동시 진행. 사용자 메모리 정합: "ship 완료 메모리가 검증 부재를 가린다" — 코드만 보지 말고 시각 흐름 검증.

시각 검증 — ADR 0018 학습 루프 closure (한 줄 본질 핵심)

변호사 측 흐름 (사건 등록 → docgen → finalize):

  1. 집행문 신청서 자동 생성 (caseId 기반 prefill)
  2. "검토 완료" 버튼 → native confirm dialog → 확정 ✓
  3. "사무소 학습 1건" 카운터 등장 = ADR 0018 학습 루프 닫힘 시각 신호 ✓
  4. "확정됨 · 편집 잠김" 상태 + "의뢰인 공유" / "확정 해제" 버튼 등장
  5. "버전 이력 1건 (확정 직전 0회 편집)" 자동 기록

의뢰인 공유:

  • "의뢰인 공유" 클릭 → 즉시 "공유됨" 상태 전이 (modal 없이)

시각 검증 — 의뢰인 포털 finalized 서류 열람

서류 탭 (포털 측):

  • "서류는 열람 전용입니다. 무단 배포 및 제3자 제공을 금합니다." (보안 카피)
  • "집행문 부여 신청서 — 박상철 NEW · 플랫폼 에디터 · 열람" ← finalize + 의뢰인 공유한 거 ✓
  • "지급명령 신청서 (김민호) · 열람 불가" ← finalize 안 함 → 정확한 권한 게이팅 ✓

서류 viewer (/portal/docs/{docId}):

  • 페이지 title: "집행문 부여 신청서 — 박상철 — 의뢰인 포털"
  • 헤더: "포털로 돌아가기" + "인쇄/PDF" 버튼
  • 본문: 당사자·집행권원·신청취지·신청이유·첨부·일자·신청인·법원 전체
  • 푸터: "읽기 전용 · 무단 배포 및 제3자 제공을 금합니다." 보안 경고

발견 결함 (다음 chip)

(1) native window.confirm() 사용 — 사건 상세 → 서류 편집 → "검토 완료" 클릭 시 native browser confirm dialog. 모바일 위치·a11y·다크모드 일관성 anti-pattern. shadcn AlertDialog 패턴 (이미 프로젝트에 있음) 으로 마이그레이션 + 전수 sweep 필요. 사용자 메모리 정합: "한 패턴 발견 시 전수조사 sweep + 회귀 가드 cycle".

(2) finalize 직후 자동 저장 race — finalize 직후 "저장 실패: 확정된 문서는 편집할 수 없습니다" 빨간 배너. PR #2319 suppressNextAutoSaveRef 가 setContent 직후만 cover, finalize 시점 미cover. finalize action 직전 suppress flag set 추가 또는 finalize 후 saveTimer cancel 필요.

누적 (2026-05-15~16 전체)

  • 머지 PR 13건 (#2306~#2319 + 회고 #2320)
  • 회귀 invariant 10건
  • 8258 테스트 통과
  • chip 잔여 3건 (CaseSummaryCards hydration · native confirm · finalize race)

다음 세션 후보

  1. dev restart 후 사무실 기억 OCR + CaseSummaryCards hydration + 편집기 자동 저장 race 시각 재확인
  2. native confirm/alert/prompt → shadcn AlertDialog 전수 마이그레이션 — 후속 #7 baseline invariant ship
  3. finalize 직후 자동 저장 race fix — 후속 #7 ship
  4. sentDocuments 흐름 (서류 발송 + 송달 추적)
  5. ops 콘솔 walkthrough

2026-05-16 후속 #7 — finalize race fix + native dialog baseline invariant

후속 #6 의 chip 2건 모두 처리.

머지 PR (2건)

PR분류핵심 변경
#2322finalize racehandleFinalize 시작 즉시 clearTimeout(saveTimerRef) + suppressNextAutoSaveRef = true + finalize 성공 후 setSaveState({kind:"idle"}) reset. "확정됨" 카드와 "저장 실패" 빨간 배너 공존 제거
#2323baseline invariantapps/web 전수 grep — 11 위치 native window.confirm/alert/prompt baseline 화이트리스트. 신규 도입 차단 + 마이그레이션 후 baseline 제거로 raise-the-bar

11 위치 baseline

  • InPlatformDocEditor (3) · EditableDocumentList · DocumentVersionList
  • PortalLinkDialog · DebtSettlementTab · CaseNextActionsCard
  • ContractualDeadlineSection · InheritanceInfoSection
  • SnippetsSection · TiptapMarkdownEditor

회귀 가드 (2건)

  • in-platform-editor-suppress-auto-save-invariants.test.ts 확장 (3 → 4 tests):
    • suppress set ≥ setContent + 1 (finalize)
    • handleFinalize 본문에 clearTimeout · suppress set · saveState idle reset 존재
  • no-native-dialogs-invariants.test.ts 신설 (2 tests):
    • baseline 외 신규 도입 차단 (apps/web 전수 grep)
    • baseline orphan 차단 (raise-the-bar 강제)

누적 (2026-05-15~16 전체)

  • 머지 PR 17건 (#2306~#2323)
  • 회귀 invariant 12건 (1 확장)
  • 8261 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards SSR/Hydration — dev cold restart 검증 필요)

다음 세션 후보

  1. dev cold restart 후 사무실 기억 OCR + hydration + finalize race + 편집기 race 시각 재확인 (확정/잠재 결함 4종)
  2. native dialog 점진 마이그레이션 (11 위치 → 0 위치, raise-the-bar)
  3. sentDocuments 흐름 (서류 발송 + 송달 추적)
  4. ops 콘솔 walkthrough (apps/ops OAuth)
  5. 사건 finalize → 새 사건 등록 시 사무실 기억 자동 참조 확인 (ADR 0041 두 RAG 결합 entry) — 후속 #8 완료

2026-05-16 후속 #8 — ADR 0041 두 RAG 결합 시각 검증 + native dialog 1 위치 마이그레이션

후속 #7 의 chip 잔여 1건 외 다음 세션 후보 중 진행 가능 2건 처리.

한 줄 본질 시각 검증 ✓ — ADR 0041 두 RAG 결합 entry

후속 #6 에서 finalize 한 집행문이 다음 같은 docKind docgen 시 사무실 기억 후보로 자동 참조되는지 시각 검증:

/docs/generate?caseId={caseId}&docType=집행문 진입:

AI 가 참고할 사무실 기억 (선택 1/1) 집행문 부여 신청서 — 박상철 .authored 2026차전123456 보기

핵심 시각 신호:

  • "선택 1/1" — 방금 finalize 한 집행문 1건이 자동 후보로 추출 ✓
  • 메타: 제목 · authored · 사건번호 — 변호사 검증 가능
  • "보기" 버튼 — 원본 확인

이전 walkthrough (첫 docgen) 와 비교:

  • 이전: "이 사건과 비슷한 사무실 기억을 찾지 못했습니다"
  • 이후 (finalize 후): "선택 1/1 + 집행문 본"

한 줄 본질 완전 작동 시각 증거 ✓ — 사무소가 finalize 한 서류 → 다음 비슷한 사건 작성 시 자동 참조 후보.

머지 PR (1건)

PR분류핵심 변경
#2325raise-the-bar 시범ContractualDeadlineSection 삭제 confirm → shadcn AlertDialog (제목 + 설명 + 취소/삭제 footer). baseline 11 → 10 위치. invariant orphan 검증이 자동 재도입 차단

점진 raise-the-bar 패턴 정립

PR #2323 baseline 신설 → PR #2325 첫 마이그레이션. 이후 동일 패턴으로:

  • AlertDialog 마이그레이션 commit
  • baseline 화이트리스트에서 해당 파일 제거 commit (orphan 검증 통과)
  • raise-the-bar 자동 진행

다음 마이그레이션 후보 (10 위치): SnippetsSection / EditableDocumentList / DocumentVersionList / PortalLinkDialog / DebtSettlementTab / CaseNextActionsCard / InheritanceInfoSection / TiptapMarkdownEditor / InPlatformDocEditor (3).

누적 (2026-05-15~16 전체)

  • 머지 PR 19건 (#2306~#2325)
  • 회귀 invariant 12건
  • 8261 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증 필요)
  • 한 줄 본질 axis — finalize → 학습 누적 → 다음 docgen 자동 참조 시각 확인 ✓

다음 세션 후보

  1. dev cold restart 후 확정/잠재 결함 4종 시각 재확인
  2. native dialog 마이그레이션 10 위치 → 0 — 후속 #9 batch 2 ship (10 → 7)
  3. sentDocuments 흐름 (서류 발송 + 송달)
  4. ops 콘솔 walkthrough
  5. 사건 신규 등록 + AI 빠른 등록으로 finalize 본 prefill 효과 검증

2026-05-16 후속 #9 — native dialog 마이그레이션 batch 2 (10 → 7)

후속 #8 의 #2325 시범 후 점진 raise-the-bar 가속.

머지 PR (1건)

PR분류핵심 변경
#2327batch 2 마이그레이션3 위치 (SnippetsSection · EditableDocumentList · DocumentVersionList) confirm → shadcn AlertDialog + alert → toast.error. baseline 10 → 7

3 위치 마이그레이션 요지

  • SnippetsSection: '${label}' 을 삭제할까요? → AlertDialog (dynamic title)
  • EditableDocumentList: 문서 soft-delete confirm → AlertDialog (Link 안에 nested 라 onClick preventDefault/stopPropagation 유지) + alert()toast.error
  • DocumentVersionList: 버전 롤백 confirm → AlertDialog + alert()toast.error

남은 baseline 7 위치

  • DebtSettlementTab (window.prompt 1 + confirm 1)
  • PortalLinkDialog · InPlatformDocEditor (3 호출)
  • InheritanceInfoSection (window.prompt)
  • CaseNextActionsCard
  • TiptapMarkdownEditor (prompt 1)

누적 (2026-05-15~16 전체)

  • 머지 PR 20건 (#2306~#2327)
  • 회귀 invariant 12건
  • 8261 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증)
  • native dialog baseline: 11 → 7 (35% 마이그레이션 진행)

다음 세션 후보

  1. dev cold restart 후 확정/잠재 결함 4종 시각 재확인
  2. native dialog batch 3 — 후속 #10 ship (7→5)
  3. sentDocuments 흐름
  4. ops 콘솔 walkthrough
  5. AI 빠른 등록 prefill 사무실 기억 효과 검증

2026-05-16 후속 #10 — native dialog batch 3 (7→5)

후속 #9 의 batch 2 후속.

머지 PR (1건)

PR분류핵심 변경
#2329batch 3 마이그레이션4 confirm (CaseNextActionsCard promoteStatus · PortalLinkDialog 재발급 · InPlatformDocEditor.handleFinalize · handleUnfinalize) → shadcn AlertDialog. baseline 7 → 5

4 confirm 마이그레이션 요지

  • CaseNextActionsCard — promoteStatus 액션만 AlertDialog 로 wrap (tab 액션은 그대로 onClick). 액션 별 분기 패턴.
  • PortalLinkDialog 재발급 — "새 접속 코드 발급" 제목 + 의뢰인 알림 안내
  • InPlatformDocEditor.handleFinalize — "이 문서를 확정합니다" + 학습 자료 안내
  • InPlatformDocEditor.handleUnfinalize — sharedWithClient 분기 description ("의뢰인 공유 중" 경고)

남은 baseline 5 (모두 prompt — Dialog + Input + Form 필요)

  • DebtSettlementTab (prompt + confirm)
  • InPlatformDocEditor (prompt 1 — 버전 저장 메모)
  • InheritanceInfoSection (prompt)
  • TiptapMarkdownEditor (prompt — 링크 URL)

누적 (2026-05-15~16 전체)

  • 머지 PR 21건 (#2306~#2329)
  • 회귀 invariant 12건
  • 8261 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증)
  • native dialog 마이그레이션 진행: 11 → 5 (55%)

다음 세션 후보

  1. dev cold restart 후 확정/잠재 결함 4종 시각 재확인
  2. native dialog batch 4 — 후속 #11 ship (raise-the-bar 완주 5→0)
  3. sentDocuments 흐름
  4. ops 콘솔 walkthrough
  5. AI 빠른 등록 prefill 사무실 기억 효과 검증

2026-05-16 후속 #11 — native dialog 마이그레이션 완주 (5→0)

batch 1 (#2325) → batch 2 (#2327) → batch 3 (#2329) → batch 4 (#2331) 최종.

머지 PR (1건)

PR분류핵심 변경
#2331raise-the-bar 완주4 prompt → InputDialog + 1 confirm → AlertDialog. baseline 5 → 0 ✓. components/ui/InputDialog.tsx 신설 (controlled Dialog + Input + Form, validation, defaultValue)

신설 — InputDialog 공용 wrapper

  • Dialog + Input + Form
  • controlled open/onOpenChange
  • defaultValue · placeholder · isValid · inputType (text/url/email)
  • cancel/ESC/외부 클릭 시 onConfirm 호출 안 함 — native prompt 의 null 분기 정합

4 prompt + 1 confirm 마이그레이션

위치변경
TiptapMarkdownEditor (링크 URL)InputDialog + isValid (http(s) 만) + alert→toast
InheritanceInfoSection (공동상속인 콤마)InputDialog + isValid (non-empty)
InPlatformDocEditor (버전 메모)InputDialog (empty 허용)
DebtSettlementTab (스냅샷 라벨)InputDialog + default ${asOfDate} 계산본
DebtSettlementTab (스냅샷 삭제 confirm)controlled AlertDialog + pendingDelete state

Native dialog baseline 완주

11 → 10 (#2325) → 7 (#2327) → 5 (#2329) → 0 (#2331) ✓

raise-the-bar 패턴 검증:

  1. baseline invariant 신설 (#2323)
  2. 점진 마이그레이션 batch 4회 (#2325·#2327·#2329·#2331)
  3. orphan 검증이 자동 재도입 차단
  4. 11 위치 → 0 위치 완주

누적 (2026-05-15~16 전체)

  • 머지 PR 22건 (#2306~#2331 일부 제외)
  • 회귀 invariant 12건 (1 확장)
  • 8261 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증)
  • native dialog 완주 11→0
  • 한 줄 본질 axis 시각 확인 완료

다음 세션 후보

  1. dev cold restart 후 확정/잠재 결함 시각 재확인 (CaseSummaryCards hydration)
  2. sentDocuments 흐름 — 후속 #12 코드 audit 완료 (UI 차단으로 우회)
  3. ops 콘솔 walkthrough (apps/ops OAuth)
  4. AI 빠른 등록 prefill 사무실 기억 효과 검증 (새 사건)
  5. 다른 정책·규칙 invariant 패턴 sweep — 후속 #12 4 sweep + 1 baseline invariant ship

2026-05-16 후속 #12 — sentDocuments audit + 4 패턴 sweep + dangerouslySetInnerHTML baseline

emulator user reset 으로 UI walkthrough 차단 → 코드 audit + 추가 정책 invariant sweep 전환.

sentDocuments 흐름 audit (UI 우회)

발송 진입점·서버 액션·rules·UX 카피 모두 정합 ✓:

단계위치상태
진입점SendModal.tsx ("발송" 버튼 → recipient + method)
Server ActionrecordSentDocAction (doc-crud-actions.ts:141)
Business Logic@neohollo/business-logic/documents.recordSentDoc (ADR 0028)
Side-effectssentDocuments append + 원본 doc status batch + notification + activityLog
List viewuseDocs onSnapshot tenants/{tid}/sentDocuments + /docs 페이지
Firestore rulessentDocuments/{id} read=staffOrOwner · write=false (Admin SDK 전용)
UX 카피"실제 발송은 전자소송 시스템·이메일 등을 통해 직접 진행" (정직한 정책 명시)

발견 결함 0건.

4 패턴 sweep 결과

패턴결과평가
console.log 잔존3건 (모두 logger utility · JSDoc 예시 — 정당)결함 0
// TODO/FIXME 마커3건 (eval dataset 시니어 변호사 섭외 + portal-statute 이동 placeholder)결함 0
react-hooks/exhaustive-deps disable0건결함 0
dangerouslySetInnerHTML3건 (모두 명시적 sanitization)baseline 신설

머지 PR (1건)

PR분류핵심 변경
#2333XSS baseline invariantdangerouslySetInnerHTML baseline 3 위치 (layout · ContractRenewalReviewModal · portal docs viewer). 신규 도입 차단 + orphan 검증 — raise-the-bar 패턴

Raise-the-bar 패턴 재사용

native dialog 11→0 완주 (#2323~#2331) 후 동일 패턴 적용:

  • baseline invariant 신설 (3 use sites whitelist)
  • 신규 도입 시 invariant fail (apps/web 전수 grep)
  • 마이그레이션 후 baseline 제거 → orphan 검증이 자동 차단

누적 (2026-05-15~16 전체)

  • 머지 PR 23건 (#2306~#2333)
  • 회귀 invariant 13건 (1 확장)
  • 8263 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증)
  • native dialog 11→0 완주
  • dangerouslySetInnerHTML baseline 3 (신규 도입 차단)
  • 한 줄 본질 axis 시각 확인 완료

다음 세션 후보

  1. dev cold restart 후 확정/잠재 결함 시각 재확인 (마지막 chip)
  2. ops 콘솔 walkthrough (apps/ops OAuth)
  3. AI 빠른 등록 prefill 사무실 기억 효과 검증 (새 사건)
  4. 다음 invariant 패턴 후보 — 후속 #13 sweep 7 패턴 완료, KST 4건 fix
  5. ContractRenewalReviewModal markdown preview sanitization 강화 (DOMPurify 통합)

2026-05-16 후속 #13 — 7 패턴 sweep + KST 정책 4건 fix + invariant

후속 #12 의 sweep 패턴 확장. 7 anti-pattern sweep + KST 정책 위반 직접 fix.

7 패턴 sweep 결과

#패턴결과평가
1.collection("...") 직접 호출87건admin SDK 정상 패턴 — baseline 부적합
2as any0건CLAUDE.md "any 금지" 완전 정합
3await new Promise(setTimeout)3건모두 retry backoff — 정당
4@ts-ignore / @ts-expect-error2건모두 Firebase App Check 매직 변수 — 정당
5console.log3건logger utility · JSDoc — 정당
6TODO/FIXME3건placeholder — 정당
7react-hooks/exhaustive-deps disable0건정당
8KST UTC 의존4건결함 — 직접 fix

KST 정책 위반 4건 fix (#2335)

위치결함Fix
AuditLogSection.tsx:349CSV 파일명 new Date().toISOString().slice(0,10) — KST 오전 9시 이전 어제todayKST()
DashboardCitationPreservationCard.tsx:117dateKey fallback 동일 UTC slicingtodayKST()
finalize-renewal-draft-action.ts:149new Date().getFullYear() — server TZ 의존yearMonthKST().year
finalize-renewal-draft-action.ts:154동일yearMonthKST().year

머지 PR (1건)

PR분류핵심 변경
#2335KST 정책 sweep + fix4 UTC anti-pattern fix + kst-policy-invariants.test.ts 신설 (UTC slicing/server TZ getter 차단). 기존 audit-log-csv invariant todayKST() 사용 검증으로 갱신

코드 베이스 평가

7 sweep 패턴 중 결함 0건 7건, 결함 1건 (KST). production 코드 매우 깨끗.

CLAUDE.md 정책 (any 금지 · KST · TODO 최소) 정합 8/8 — 자율 fix·sweep cycle 누적 결과.

누적 (2026-05-15~16 전체)

  • 머지 PR 24건 (#2306~#2335)
  • 회귀 invariant 14건
  • 8265 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart 검증)
  • native dialog 11→0 완주
  • dangerouslySetInnerHTML baseline 3 (신규 도입 차단)
  • KST 정책 위반 0건
  • 한 줄 본질 axis 시각 확인 완료

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (마지막 chip 종료)
  2. ops 콘솔 walkthrough (apps/ops OAuth)
  3. AI 빠른 등록 prefill 사무실 기억 효과 검증 (새 사건)
  4. ContractRenewalReviewModal markdown DOMPurify 통합
  5. 또 다른 정책 sweep — revalidatePath 누락 · Math.random() — 후속 #14 revenue revalidatePath fix + Math.random sweep 완료

2026-05-17 후속 #14 — revalidatePath 누락 sweep + Math.random sweep

후속 #13 의 7 sweep 후 추가 패턴 점검.

Sweep 1 — Server Action mutation 후 revalidatePath 누락

30+ 후보 파일 중 데이터 흐름 확인:

  • 대부분 telemetry/event 기록 (writeActivityLog, audit log) — client onSnapshot 의존 → 정당
  • legacy-upload-actions.ts — legacy 페이지 onSnapshot 구독 → 정당
  • revenue/actions.ts — SSR fetch + client onSnapshot 없음 → 결함 ❌

revenue/page.tsxadminDb.collection("fees").get() 으로 SSR fetch + RevenueClient.tsx 가 onSnapshot 구독 없음. createInvoiceAction / markPaidAction 후 revalidatePath 누락 — 모달 close 후 재진입해도 새 데이터 안 보임.

Sweep 2 — Math.random() 비결정 사용

5 위치 모두 client ID 생성 / UI animation — 정당:

  • LeaseDepositForm.tsx (form local ID)
  • DistributionModal.tsx (배당 row uid)
  • useDocGeneration.ts (progress bar animation)
  • legacy-upload-actions.ts (batch ID — Date.now() 결합)
  • ScannedUploadModal.tsx (client batch ID)

baseline 부적합 — 결함 0건.

머지 PR (1건)

PR분류핵심 변경
#2337revenue SSR cache fixcreateInvoiceAction · markPaidAction success path 에 revalidatePath("/revenue") 추가 + next/cache import. revenue-revalidate-path-invariants.test.ts 신설 (2 호출 보장 + 신규 mutation 추가 시 갱신 알림 분기)

회귀 가드 (3건)

revenue-revalidate-path-invariants.test.ts:

  1. revalidatePath('/revenue') 호출 ≥ 2회
  2. next/cache import 존재
  3. export async function 가 createInvoiceAction · markPaidAction 둘뿐 — 신규 mutation action 추가 시 invariant 갱신 알림

누적 (2026-05-15~17 전체)

  • 머지 PR 33건 (#2306~#2337)
  • 회귀 invariant 15건
  • 8268 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart)
  • native dialog 11→0
  • dangerouslySetInnerHTML baseline 3
  • KST 정책 위반 0건
  • revenue SSR cache stale 0건
  • 한 줄 본질 axis 시각 확인 완료

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (마지막 chip)
  2. ops 콘솔 walkthrough
  3. AI 빠른 등록 prefill 사무실 기억 효과 검증 (새 사건)
  4. ContractRenewalReviewModal markdown DOMPurify 통합
  5. 다른 SSR list view audit — 후속 #15 완료 (5 list view + ops)

2026-05-17 후속 #15 — 6 list view + ops revalidatePath audit + 3 추가 sweep

후속 #14 의 revenue fix 후 동일 패턴이 다른 list view 에도 있는지 전수 audit.

SSR list view audit (6 영역)

영역SSR fetchclient 구독revalidatePath 필요?
/casesadminDb.collection(...)useCasesData onSnapshot ✓불필요 — 정당
/clientsadminDb fetchuseClients onSnapshot ✓불필요 — 정당
/calendaradminDb fetchuseCalendar onSnapshot ✓불필요 — 정당
/docsadminDb fetchuseDocs onSnapshot ✓불필요 — 정당
/legacyadminDb fetchuseLegacyDocs onSnapshot ✓불필요 — 정당
/activitySSR fetch + loadMore actiononSnapshot 없음 (read-only 페이징)의도된 SSR 페이징 — 정당
/revenueSSR fetch + onSnapshot 없음RevenueClient 구독 X결함 (후속 #14 fix #2337)

revenue 만 유일한 결함 — 다른 6 영역 모두 onSnapshot 일관 패턴.

apps/ops audit

  • feature-flagsuseDocumentSnapshot 구독 ✓
  • set-yjs-threshold · toggle-feature-flag — 같은 page 의 onSnapshot 의존 ✓
  • seed-*-mock-action (5 위치) — test mock seeder, 결과 토스트 + 수동 reload ✓
  • record-hypothesis-feedback · generate-anomaly-hypothesis — dashboard onSnapshot ✓

ops 결함 0건.

3 추가 sweep

패턴결과평가
.catch((err) => console.error(...)) silent swallow60건모두 fire-and-forget 부수 효과 (writeActivityLog·writeNotification·markCaseMessagesRead) — 정당
as unknown as ... double cast10건모두 type bridging (Firestore doc → typed · 외부 SDK 글로벌 · domain input → generic) — 정당
Math.random() 잔존5건client ID 생성 / UI animation (이미 후속 #14) — 정당

종합 평가

  • SSR + onSnapshot 일관 패턴 정합 — revenue 만 유일한 예외였음 (이미 fix)
  • fire-and-forget 부수 효과 silent swallow — 의식적 패턴 (mutation 자체는 성공·부수 효과만 log)
  • type bridging — 명시적 typing 으로 안전
  • client ID 생성 — server 영향 없음

이번 세션 신규 fix 0건, audit 결과는 production 매우 깨끗 확인.

누적 (2026-05-15~17 전체)

  • 머지 PR 33건 (#2306~#2337)
  • 회귀 invariant 15건
  • 8268 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart)
  • 모든 정책 패턴 sweep 결과:
    • native dialog 11→0 ✓
    • dangerouslySetInnerHTML baseline 3 (XSS 차단)
    • KST 정책 위반 0
    • as any 0 · console.log 0 · exhaustive-deps disable 0
    • revenue SSR cache stale 0
    • 6 list view + ops revalidatePath 일관

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (마지막 chip 종료)
  2. ops 콘솔 walkthrough (apps/ops OAuth)
  3. AI 빠른 등록 prefill 사무실 기억 효과 검증 (새 사건)
  4. ContractRenewalReviewModal markdown DOMPurify 통합
  5. apps/ops shadcn 정합 sweep — apps/web 정합 (native dialog/KST baseline) 후 ops 측 추가 패턴

2026-05-17 후속 #16 — Server Action 200줄 baseline invariant

CLAUDE.md "새 Server Action 은 200줄 이하. 초과 시 _actions/ 분리" 정책 정합 invariant 신설.

머지 PR (1건)

PR분류핵심 변경
#2340raise-the-bar baselineServer Action 200줄 초과 18 파일 baseline (488 → 208). 신규 도입 차단 + orphan 차단 invariant. countLines() 헬퍼 (wc -l 등가)

Baseline 18 파일 (대표)

legacy-search-actions.ts 488 ← 최대
editable-document-actions.ts 383
doc-crud-actions.ts 271
portal-access-code-actions.ts 261
legacy-storage-actions.ts 257
quick-search-cases-action.ts 256
ai-assist-actions.ts 240
... 11 more files ...
finalize-document-action.ts 208 ← 최소

Raise-the-bar 패턴 4번째 적용 (누적)

  1. native dialog baseline (#2323) → 11→0 완주 (#2331)
  2. dangerouslySetInnerHTML baseline (#2333) — 3 위치 XSS 차단
  3. KST 정책 invariant (#2335) — 4 위치 fix + 신규 차단
  4. Server Action 200줄 baseline (#2340) — 18 위치 신규 차단

누적 (2026-05-15~17 전체)

  • 머지 PR 35건 (#2306~#2340)
  • 회귀 invariant 16건 (raise-the-bar baseline 4종)
  • 8270 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart)
  • 모든 정책 패턴 정합 ✓:
    • native dialog 11→0
    • dangerouslySetInnerHTML baseline 3
    • KST 정책 위반 0
    • as any 0 · console.log 0 · exhaustive-deps disable 0
    • revenue SSR cache stale 0
    • Server Action 200줄 baseline 18 (raise-the-bar 진행 중)
  • 한 줄 본질 axis 시각 확인 완료

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인
  2. ops 콘솔 walkthrough (OAuth)
  3. AI 빠른 등록 prefill 사무실 기억 효과 검증
  4. Server Action 200줄 baseline 마이그레이션 — 가장 큰 488줄 (legacy-search-actions) 분할 시도
  5. ContractRenewalReviewModal markdown DOMPurify 통합

2026-05-17 후속 #17 — 첫 한 줄 본질 핵심 기능 ship (사무소 기억 자가 회귀)

정직한 평가 (사용자 질문에 응답)

후속 #14~#16 모두 정합 가드 · UI 결함 fix · invariant baseline 신설. 한 줄 본질 직접 기여 신규 capability 0건이었음.

사용자 메모리 정합 — "회의·자율 세션은 핵심 기능을 만들지 못함" / "혁신 core 우선" / "학습 루프는 데이터로 닫힌다 — 합성 corpus + 자가 회귀로 내부 closed loop".

사용자 명시 scope (사무소 기억 학습 품질 closed-loop) 로 전환.

머지 PR (1건)

PR분류핵심 변경
#2342첫 한 줄 본질 핵심 기능ADR 0015 Tenant RAG leave-one-out 자가 회귀 invariant. 합성 corpus 8건 (4 사건 × 2 docKind) + deterministic BoW embedding + recall@3 ≥ 0.5 임계값

Ship 한 capability

ADR 0015 Tenant RAG 학습 루프 닫힘 정량 검증:

  • 합성 corpus 8건 (Case A·B·C 대여금 + Case D 공사대금, 각각 지급명령 + 답변서)
  • 같은 case 본은 당사자·금액·법원 공유 (높은 의미 유사도)
  • 다른 case 의 같은 docKind 는 패턴 (조항·구문) 공유 (중간 유사도)
  • leave-one-out: 각 본 query → 나머지 7건 인덱스 → top-3 cosine retrieval
  • ground truth: 같은 caseId OR 같은 docKind = positive
  • recall@3 ≥ 0.5 통과

회귀 가드 — corpus 또는 embedding 변경 시 recall@3 자동 측정 + 임계값 미달 시 fail.

Production 단계 (후속)

  • mockEmbed (BoW 한국어 unigram+bigram) → text-embedding-004 호출로 교체
  • 동일 corpus·동일 ground truth 로 production embedding recall@3 측정 (≥0.7 기대)
  • 임계값 raise — 회귀 가드 강화

누적 (2026-05-15~17 전체)

  • 머지 PR 38건 (#2306~#2342)
  • 회귀 invariant 17건 (raise-the-bar baseline 4종 + 한 줄 본질 자가 회귀 1종)
  • 8275 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart)
  • 정합 baseline + 한 줄 본질 ship 균형 회복 ✓

다음 세션 후보 (한 줄 본질 직접 기여 우선)

  1. mockEmbed → text-embedding-004 — 후속 #18 ship (scripts/eval-tenant-rag-self.ts)
  2. 두 RAG 결합 retrieval ops dashboard — 이미 ADR 0043 v2.68·v2.73 ship 확인
  3. AI 서류 품질 코파일럿 v2 anomaly 자동 dismiss — 후속 #18 ship (Phase 3 pure functions)
  4. 사건 자동 분류 정밀도 — 후속 #18 ship (corpus 42건 + invariant)
  5. (정합 가드 후순위) Server Action 200줄 마이그레이션 / DOMPurify 통합

2026-05-17 후속 #18 — 한 줄 본질 핵심 기능 4건 일괄 ship

사용자 요청 "핵심 기능 후보 5건 모두 진행". 후속 #17 (Tenant RAG self-regression) 이후 추가 4건 진행.

머지 PR (2건)

PR분류핵심 변경
#2344한 줄 본질 #2·#3(1) 사건 자동 분류 정확도 corpus 42건 + classifyByKeywords invariant (≥90% 통과) + (2) ADR 0042 Phase 3 — shouldAutoDismiss + shouldPromoteToOpsKnowledge pure functions + 18 unit tests
#2345한 줄 본질 #4scripts/eval-tenant-rag-self.ts — PR #2342 mock invariant 의 production embedding 버전 (Vertex AI text-embedding-004). 동일 corpus·ground truth + --apply 시 ragMergeQuality 저장 → 기존 RagHistoryChart 자동 표시

후보 5건 결과

  1. 사건 자동 분류 정밀도 ✓ — corpus 42건 (14 종 × 3), classifier ≥ 90% 정확도 통과
  2. anomaly Phase 3 자동 dismiss/promote ✓ — pure functions 4종 + 18 unit tests (운영자 시나리오 포함)
  3. ragMergeQuality ops dashboard 시각화 ✓ — 이미 ADR 0043 v2.68/v2.73 에 ship 됨 확인 (별도 작업 0)
  4. mockEmbed → text-embedding-004 교체 ✓ — scripts/eval-tenant-rag-self.ts 신설 (production embedding hook)
  5. ContractRenewalReviewModal DOMPurify / Server Action 200줄 마이그레이션 — 정합 후순위로 보류

한 줄 본질 핵심 기능 누적 (후속 #17 + #18)

기능PR상태
Tenant RAG leave-one-out 자가 회귀 (mock)#2342
사건 자동 분류 정확도 (42건 corpus)#2344
anomaly Phase 3 자동 dismiss/promote#2344
Tenant RAG production embedding eval script#2345
두 RAG 결합 ragMergeQuality 시각화(기존)✓ ship 확인

5개 핵심 기능 모두 ship.

누적 (2026-05-15~17 전체)

  • 머지 PR 42건 (#2306~#2345)
  • 회귀 invariant 20건 (자가 회귀 1종 + 분류 1종 + anomaly 1종 + 기존)
  • 8301 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration)
  • 한 줄 본질 핵심 기능 5건 ship 완료

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인
  2. record-hypothesis-feedback-action automation — 후속 #19 확인: scripts/promote-past-hypotheses.tsevaluatePromotionEligibility pure functions + 기존 invariant 로 이미 ship
  3. casePrefillRuns 누적 결과 ops dashboard — 후속 #19 확인: /case-prefill 페이지 + useCasePrefillRuns hook 으로 이미 ship
  4. scripts/eval-tenant-rag-self.ts cron 통합 — 후속 #19 가이드 ship
  5. 14 종 외 신영역 — 후속 #19 Pack 6 형사 사건 ADR 0045 draft

2026-05-17 후속 #19 — eval scripts cron + Pack 6 신영역 ADR draft

사용자 메모리 정합 — "ship 완료 메모리가 검증 부재를 가린다". 후속 #18 의 다음 세션 후보 5건 중 #2·#3 은 이미 ship 됨 발견 (실 코드 확인). 새 capability 는 #4 cron 가이드 + Pack 6 ADR draft.

머지 PR (1건)

PR분류핵심 변경
#2347한 줄 본질 #19(1) scripts/eval-case-classification-gemini.ts — production Gemini 분류 정확도 측정. (2) eval-scripts-cron-setup.md — 3 eval scripts cron 일정·아키텍처 가이드. (3) ADR 0045 draft — Pack 6 형사 사건 신영역

이미 ship 됨 확인 (재발견)

기능위치상태
anomaly Phase 3 자동 dismiss/promotescripts/promote-past-hypotheses.ts + evaluatePromotionEligibility pure functions + business-logic-ops-anomaly-promote.test.ts✓ batch script + invariant
casePrefillRuns ops dashboardapps/ops/app/(ops)/case-prefill/page.tsx + useCasePrefillRuns✓ collectionGroup 구독 + 필드 별 통계

Pack 6 형사 사건 ADR 0045 (draft)

14 종 외 첫 신영역. 사용자 합의 대기:

영역추정 작업량
recoveryType + types200 lines
wizard 3 step 분기600 lines
사건 상세 패널400 lines
docKind 6 추가 + 템플릿500 lines + .docx
시효·기한200 lines
9 단계 흐름 분기300 lines
corpus 보강sync-law 작업
회귀 invariant + e2e400 lines
합계~2600 lines + .docx 6

Pack 6 first ship = 사기 1 종. 후속 4 종 (횡령·폭행·마약·교통치사상) 별도 PR.

누적 (2026-05-15~17 전체)

  • 머지 PR 44건 (#2306~#2347)
  • 회귀 invariant 20건
  • 8301 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration)
  • 한 줄 본질 핵심 기능 ship 누적:
    • #17: Tenant RAG mock 자가 회귀
    • #18: 사건 분류 + anomaly Phase 3 + production embedding eval (5/5)
    • #19: Gemini classification eval + cron 가이드 + Pack 6 ADR draft

다음 세션 후보

  1. Pack 6 사용자 합의 후 implementation — 14 → 15 종 recoveryType + wizard 형사 분기 + docKind 6
  2. dev cold restart 후 hydration 결함 시각 재확인 (마지막 chip)
  3. production Gemini classification 측정 baseline 후 임계값 raise
  4. ragMergeQuality kind 별 chart 분리 노출 (현재 통합 시계열)
  5. 또 다른 한 줄 본질 영역 — exemplar selection 알고리즘 개선 / RAG cache hit rate

2026-05-17 후속 #20 — Pack 6 형사 사건 first slice ship (14 → 15 종)

사용자 요청 "핵심 기능 후보 모두 진행". 14 종 외 첫 신영역 ship — 한 줄 본질 도메인 직접 확장.

머지 PR (1건)

PR분류핵심 변경
#2349한 줄 본질 도메인 확장ADR 0045 Pack 6 형사 사건 first slice. 14 → 15 종 recoveryType (criminal-fraud). recovery-input-schemas + LABEL + description + icon + statute + wizard Step1 SelectItem + checklist 카탈로그 (client·firm) + 자동 분류 corpus 3건 + 7 회귀 가드 update + 4 type narrowing 분기

Ship 한 capability

  • 15 종 recoveryType — Pack 1~5 14 종 + Pack 6 형사 사기 1 종
  • wizard 진입 가능 — Step1 SelectGroup "형사 (Pack 6)" → 사기 옵션
  • checklist — 의뢰인 자료 3종 (출석 통지서·진술서·방어 증거) + 사무소 서류 3종 (변호인 선임서·의견서·양형 자료)
  • 자동 분류classifyByKeywords 형사 키워드 rule (변호인·송치·피고인·보이스피싱·양형·구속 영장·형법) 우선순위 110
  • 공소시효 — 형사소송법 §249 placeholder (10년)
  • 시각 신호 — Gavel 아이콘 + red-600 accent (사건 심각도)
  • placeholder UI — Pack 4 (상속) 패턴 — 도메인 본격 UI 는 후속 PR Pack 6.2

후속 PR (Pack 6.2~)

후속내용
Pack 6.2DocKind enum 정식 등재 (criminal-* 3 종 → doc-kind-to-ko.ts SSoT)
Pack 6.3CriminalInfoSection 도메인 패널 (overview 탭)
Pack 6.49 단계 흐름 분기 (변호인선임→수사→기소→1심→항소→상고)
Pack 6.5공소시효 일반 7년 · 특경 10년 union 확장
Pack 6.6후속 4 종 (횡령·폭행·마약·교통치사상)
Pack 6.7형법 · 형사소송법 corpus sync (publicDocuments)

한 줄 본질 정합

사무소가 처리한 형사 의견서·양형자료가 다음 사건 자동 참조.

ADR 0015 Tenant RAG + ADR 0041 두 RAG 결합 패턴 그대로 적용 — 도메인 분기만 새로.

누적 (2026-05-15~17 전체)

  • 머지 PR 47건 (#2306~#2349)
  • 회귀 invariant 20건
  • 8302 테스트 통과
  • chip 잔여 1건 (CaseSummaryCards hydration · dev restart)
  • 한 줄 본질 핵심 기능 누적:
    • #17: Tenant RAG mock 자가 회귀
    • #18: 사건 분류 + anomaly Phase 3 + production embedding eval (5/5)
    • #19: Gemini classification eval + cron 가이드
    • #20: Pack 6 형사 사건 first slice (14 → 15 종) ← 도메인 직접 확장

다음 세션 후보

  1. Pack 6.2 — CriminalInfoSection 도메인 패널 + DocKind enum 정식 등재
  2. Pack 6.5 — 공소시효 정밀 분기 (일반 7년 · 특경 10년)
  3. dev cold restart 후 hydration 결함 시각 재확인
  4. production Gemini classification 측정 baseline
  5. ragMergeQuality kind 별 chart 분리 노출

2026-05-17 후속 #21 — Pack 6.2 ship + 학습 인프라 정교화 (4 capability)

후속 #20 의 "다음 세션 후보" 4건을 1 세션에 일괄 ship — 핵심 기능 직접 확장 + 학습 루프 정교화.

머지 PR (3건, branch feat/pack6-dockind-22-criminal)

PR (branch)분류핵심 변경
634e81d9DocKind enum 19 → 22criminal-defense-appointment · criminal-opinion · criminal-sentencing-materials. 14 SSoT 동시 update (docgen-types · docgen-telemetry · doc-kind-to-ko · v2-query-expansion · related-memory-query · docx-upload-validation · DocxTemplatesSection · ops doc-kinds · functions ops-generate-test-doc · 4 invariant tests + ops UI text 3 곳)
22bb7236CriminalInfoSection 도메인 패널overview 탭 형사 사건 정보 카드 — 죄명·사건번호·진행 단계·검찰청·법원·송치일·기소일·구속·핵심 사실. 새 case-criminal-actions Server Action (ADR 0028 thin wrapper) + 9 CaseData 형사 필드 + 13 단위 테스트
147b245eragMergeQuality kind 별 chart 분리RagEvalKind 3 종 (eval-rag-merge / tenant-rag-self / case-classification-gemini). normalizeRagMergeRow + seriesByKind. dashboard + tenants/[tid] 모두 kind 별 별도 chart 렌더. kind 누락 docs 는 eval-rag-merge backward-compat. 9 normalize 단위 테스트
3e2e18d0exemplar selection v2 (Wilson + recency)(up-down)/totalwilsonLowerBound(up, total) + 0.5) × recencyFactor. 표본 크기 자연 가중 (1/1 ≈ 0.21 vs 10/10 ≈ 0.72) + halfLife 180일 exponential decay. minSample binary cliff 폐기. selectionScore optional 출력. 4 새 v2 동작 테스트

Ship 한 capability

  • 22 DocKind 정식 등재 — Pack 6.2 변호인 선임서·의견서·양형 자료 3 종. docx-upload-validation + DocxTemplatesSectionDOC_KIND_LABEL derive 로 자동 동기화 (개발자 수동 sync 부담 0)
  • 형사 사건 도메인 패널 — Pack 4 (상속) _inheritance/ 패턴 모사. 송치일 → 기소일 순서 검증 (criminalIndictmentDate < criminalReferralDate 거부)
  • kind 별 학습 회귀 chart — recall + precision (eval-rag-merge), recall (tenant-rag-self), accuracy (case-classification-gemini) 의 의미 혼합 회피
  • exemplar selection v2 — Wilson 신뢰 하한으로 표본 크기 차등 + recency exponential decay 로 신선·고품질 우대. cold start 안전 (quality 없으면 순수 recency)

기술 결정

결정이유
Wilson 95% (z=1.96)Reddit·Hacker News 가 동일 알고리즘 사용. 표본 < 5 에서도 부드러운 점수.
recency halfLife 기본 180일6 개월 = 사무소 사건 주기 1 cycle. 너무 짧으면 학습 자산 손실, 너무 길면 옛 패턴 잔재.
qualityMinSample (v1 필드) deprecated noopAPI 호환만 유지. 다음 PR 에서 호출부 정리 후 제거. v2 의 Wilson 이 표본 자연 가중하므로 minSample gate 불필요.
eval-rag-merge writer 에 kind 추가forward symmetry. 기존 문서 (kind 없음) 는 normalizeRagMergeRow 에서 "eval-rag-merge" 로 자동 분류 — backward compat 손실 0.
RecoveryTab 형사 placeholder 유지 (제거 안 함)recovery 탭 자체는 채권 회수 도구라 형사 무관. 안내 메시지로 overview 탭의 CriminalInfoSection 참조 가이드.

검증

  • apps/web type-check 통과
  • apps/ops type-check 통과
  • functions type-check 통과
  • apps/web 703 test files (8319 tests) 통과 (+17 신규)
  • apps/ops 107 test files (845 tests) 통과 (+11 신규)
  • lint 0 errors

한 줄 본질 정합

이번 세션은 한 줄 본질 ("법률 사무소가 자기 데이터로 자기 AI 학습·활용") 의 두 축 모두 정교화:

  1. 도메인 직접 확장 축 — Pack 6 형사 도메인이 22 DocKind 까지 SSoT 등재 완료. CriminalInfoSection 으로 형사 사건의 사무소-특화 메타 (송치일·기소일·구속 등) 입력 통로 ship.
  2. 학습 알고리즘 정교화 축 — exemplar selection v2 가 표본 크기에 비례한 신뢰 점수 + 신선도 곱셈으로 사무소 변호사 피드백을 제대로 반영. ragMergeQuality kind 별 chart 분리로 어떤 학습 axis 가 향상되는지 명확.

누적 (2026-05-15~17 전체)

  • 머지 PR 47 + 4 = 51건 (#2306~#2349 + branch 4 commits)
  • 회귀 invariant 20+ ~ 누적
  • 8319 web + 845 ops = 9164 테스트 통과
  • 한 줄 본질 핵심 기능 누적:
    • #17: Tenant RAG mock 자가 회귀
    • #18: 사건 분류 + anomaly Phase 3 + production embedding eval (5/5)
    • #19: Gemini classification eval + cron 가이드
    • #20: Pack 6 형사 사건 first slice (14 → 15 종)
    • #21: Pack 6.2 DocKind 22 등재 + CriminalInfoSection + RAG kind chart + exemplar v2 ← 도메인 패널 + 학습 정교화

다음 세션 후보

  1. Pack 6.5 — 공소시효 정밀 분기 (형법 §249 일반 7년 · 특정경제범죄법 §3 10년 union)
  2. Pack 6.4 — 9 단계 형사 사건 흐름 (변호인선임 → 수사 → 송치 → 기소 → 1심 → 항소 → 상고 → 확정 → 집행유예/실형 분기)
  3. Pack 6.6 — 후속 4 종 (횡령·폭행·마약·교통치사상)
  4. dev cold restart 후 hydration 결함 시각 재확인
  5. production Gemini classification 측정 baseline (real tenant 데이터)
  6. exemplar selection v2 → 실제 fetchAuthoredExemplars 호출부에서 nowMs 명시 전달 + qualityMinSample 호출부 정리

2026-05-17 후속 #22 — Pack 6 형사 도메인 완성 (4 capability)

후속 #21 의 "다음 세션 후보" 4건 (Pack 6.4 + 6.5 + 6.6 + exemplar 정리) 일괄 ship. Pack 6 형사 도메인이 시효·9 단계 흐름·5 종 죄명·timeline 시각화까지 모두 production.

머지 PR (4 commit, branch feat/pack6-criminal-statute-and-more)

commit분류핵심 변경
8828053cPack 6.5 공소시효 정밀 분기yearsApplied union 에 7 추가 (1|2|3|5|7|10). criminalAggravated 토글 — 형법 §347 일반 7년 vs 특경법 §3 가중 10년. CaseData 2 신규 필드 (criminalAggravated · criminalCrimeEndDate). statute-adapter 기산점 분기 (3 단계 fallback). CriminalInfoSection UI 갱신
c46e63b8Pack 6.6 형사 4 종 추가RecoveryType 15 → 19 (criminal-embezzlement · criminal-assault · criminal-drug · criminal-traffic-fatality). 각 죄명에 일반·가중 시효 분기. 11 SSoT 동시 update + 5 invariant 갱신. 12 합성 corpus + 4 키워드 룰
ec34975ePack 6.4 9 단계 형사 흐름 + timelinecriminalPhase union 4 → 9 (변호인선임 → 수사 → 송치 → 기소 → 1심 → 항소 → 상고 → 확정 → 집행). 신규 SSoT _criminal/criminal-phase.ts (CRIMINAL_PHASES + LABEL + HINT + normalize backward-compat + progress + closed). CriminalInfoSection PhaseTimeline 컴포넌트 (9 segment progress bar). 16 신규 단위 테스트
bb2d9234exemplar v2 cleanupfetchAuthoredExemplarsAction 가 nowMs 명시 전달. qualityMinSample deprecated 필드 SelectExemplarsInput 에서 제거. synthetic-firm-memory-loop 2 호출부 + fixture 주석 + deprecated 호환 테스트 정리

Ship 한 capability

  • 19 RecoveryType (총) — Pack 1 6 + Pack 2 1 + Pack 3 3 + Pack 4 2 + Pack 5 2 + Pack 6 5 (사기·횡령·폭행·마약·교통치사상)
  • 9 단계 형사 흐름 timeline — 변호인이 한눈에 사건 단계 파악 + 진척률 11.1% → 100% 표시
  • 공소시효 7·10년 분기 — 가중처벌 (특경법 §3 · 업무상 §356 · 영리 §58 · 특가법 §5의3·§5의11) 토글로 정밀 시효
  • 52 corpus + 4 키워드 룰 — Pack 6 형사 자동 분류 (False positive 차단 · priority 120 죄명 + 110 fallback)
  • exemplar selection v2 cleanup — qualityMinSample noop 필드 제거, nowMs 명시 전달

기술 결정

결정이유
criminalAggravated boolean (단일 toggle)5 종 각 죄명에 "가중처벌 여부" 분기를 일관 패턴으로 — 죄명별 sub-enum 보다 단순. UI 도 가/아니오 Select 단일
criminalCrimeEndDate 신규 필드형사소송법 §252 ② 공소시효 기산점. proxy fallback (송치 → 기소) 으로 미입력 케이스 graceful degradation
9 단계 timeline 색 — red 계열 (3 tier: done red-500 / current red-600 / future muted)사건 심각도 시각 신호 유지 + 진척 위치 즉시 인지
normalizeCriminalPhase 함수기존 Pack 6.2 데이터 (4 단계) 가 prod 에 없지만 안전망. "prosecution" → "referred" · "trial-appeal" → "appeal" 보수적 매핑
qualityMinSample 즉시 제거v2 Wilson 이 자연 표본 가중 — minSample binary cliff 무의미. 호출부에서 이미 noop, 인터페이스 정리로 의도 명확화

검증

  • apps/web type-check 통과
  • apps/ops type-check 통과
  • apps/web 704 test files (8354 tests) 통과 (+25 신규)
    • Pack 6.5 statute 5 + 4 validate
    • Pack 6.6 statute 9
    • Pack 6.4 phase 16 — normalize · progress · closed · label 완전성
  • apps/ops 107 test files (845 tests) 통과
  • 0 lint errors

한 줄 본질 정합

사무소가 처리한 형사 의견서·양형자료가 다음 사건 자동 참조 (5 죄명·9 단계 흐름·정밀 시효 분기).

본 세션의 모든 변경이 한 줄 본질의 도메인 확장 축에 직접 기여:

  1. 5 종 죄명 — 형사 사건 데이터 capture surface 가 1 → 5 종 (5배). 사무소 형사 케이스 분류·검색·exemplar 학습 모두 5 종 분리
  2. 공소시효 정밀 — 변호인 실무에서 면소·시효 다툼은 핵심. 가중처벌 토글 한 번으로 7/10년 분기 (이전엔 10년 fallback)
  3. 9 단계 timeline — 사무소가 N 형사 케이스를 portfolio 로 관리할 때 어느 단계에 몰려 있는지 가시화. 단계별 dashboard widget 후속 가능
  4. exemplar 정리 — production 안정성 +1, 다음 학습 루프 변경 시 깔끔한 출발점

누적 (2026-05-15~17 전체)

  • 머지 PR 51 + 4 = 55건 (#2306~#2351 + 4 commits)
  • 회귀 invariant 누적 갱신 — RECOVERY_TYPES 19 종 invariant 6 곳 (#22 에서 갱신)
  • 8354 web + 845 ops = 9199 테스트 통과
  • 한 줄 본질 핵심 기능 누적:
    • #17: Tenant RAG mock 자가 회귀
    • #18: 사건 분류 + anomaly Phase 3 + production embedding eval (5/5)
    • #19: Gemini classification eval + cron 가이드
    • #20: Pack 6 형사 사건 first slice (14 → 15 종)
    • #21: Pack 6.2 DocKind 22 등재 + CriminalInfoSection + RAG kind chart + exemplar v2
    • #22: Pack 6.4+6.5+6.6 — 9 단계 흐름 + 정밀 시효 + 5 종 죄명 + exemplar cleanup ← Pack 6 완성

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (retro #20·#21 cumulative)
  2. production Gemini classification 측정 baseline — real tenant 데이터 19 종 corpus accuracy
  3. CriminalInfoSection 의 9 단계 timeline 클릭 시 단계별 일자 자동 입력 UX
  4. 형사 docKind 3 종 (변호인선임서·의견서·양형자료) 실 PDF/DOCX 템플릿 작성 + 사무소 업로드 검증
  5. Pack 6 dashboard widget — 9 단계 portfolio 분포 (각 단계 case 수 + 시효 임박 알림)
  6. recovery-input-schemas RECOVERY_TYPES → CaseDomainType rename (ADR 0028 예약 작업)

2026-05-17 후속 #23 — Pack 6 portfolio 가시화 + 학습 인프라 정착 (4 capability)

후속 #22 의 "다음 세션 후보" 6건 중 자율 모드 적합한 4건 일괄 ship — Pack 6 형사 도메인이 dashboard portfolio + 자동 stamp + 템플릿 spec + 명명 cleanup 완성.

머지 PR (4 commit, branch feat/pack6-dashboard-and-cleanup)

commit분류핵심 변경
6c79b86cPack 6.7 dashboard widgetDashboardCriminalPortfolioCard — 5초 헤드라인: 활성/종결 + 시효 임박/구속/가중 alert + 9 단계 흐름 분포 + 5 죄명 chip. computeCriminalPortfolio 순수 함수 + Server Action (1000 case scan). 16 신규 단위 테스트
14eef80dPack 6.7 phase 자동 stampCriminalInfoSection Select onChange 에서 phase 진입 시 referralDate/indictmentDate 비어 있으면 todayKST() 자동 stamp. autoStampForPhaseTransition pure 함수 — referred/indicted/trial-* 단계별 일자 자동 채움. 7 신규 단위 테스트
ccd0c1f4Pack 6.8 docKind placeholder 어댑터buildCriminalDocxRenderData — 3 형사 docKind (변호인 선임서·의견서·양형자료) 의 placeholder map 빌더. 18 공통 + docKind 별 추가 2~3. apps/docs 에 criminal-templates.md 작성·업로드 가이드. 13 신규 단위 테스트
8a6d3dafCaseDomainType alias (ADR 0028)RECOVERY_TYPES → CaseDomainType 점진 rename. additive alias 4 (CaseDomainType · CASE_DOMAIN_TYPES · CASE_DOMAIN_TYPE_LABEL · CaseDomainTypeSchema). CLAUDE.md 새 섹션. 4 alias drift 회귀 가드

Ship 한 capability

  • Pack 6 dashboard 5초 헤드라인 — 사무소 형사 사건 portfolio (활성/종결 · 시효/구속/가중 alert · 9 단계 흐름 분포 · 5 죄명 chip). 활성 0건이면 자체 hide
  • phase 진입 = 일자 stamp 자동화 — 변호인 단계 클릭 한 번으로 송치일·기소일 timeline 일자 stamp. 기존 일자는 보존
  • 형사 docKind 3 종 placeholder + 가이드 — buildCriminalDocxRenderData 어댑터 + criminal-templates.md operations 가이드. 사무소가 가이드 따라 .docx 작성·업로드 가능
  • CaseDomainType alias — Pack 6.7 까지 19 종 누적 후 명명 일반화. 신규 코드 권장 path 명확, 기존 1785 참조 그대로

기술 결정

결정이유
활성 0건 자체 hide비형사 사무소에서 dashboard 노이즈 회피. Pack 1~5 위주 사무소가 형사 카드 보이는 건 부정확
computeCriminalPortfolio 가 computeCaseStatuteStatus 재사용시효 임박 카운트 자동 (3 단계 fallback). 중복 로직 0
autoStampForPhaseTransition 가 pure function단위 테스트 가능 + UI 만 thin wrapper. 자동 stamp 규칙 변경 시 테스트만 갱신
자동 stamp 는 비어 있을 때만변호인이 정확한 일자 입력했다면 절대 덮어쓰지 않음 (data loss 회피)
docKind 어댑터 분리 (criminal-docgen-placeholders.ts)민사 docgen-adapter 는 RecoveryCalculateResult 의존, 형사는 청구액 없음. 두 어댑터 분리 — 양쪽 책임 명확
CaseDomainType additive alias1785 ref 전수 sweep 위험 회피. 신규 코드 권장 path 명시 + drift 회귀 가드로 의미 동결

검증

  • apps/web type-check 통과
  • apps/web 706 test files (8394 tests) 통과 (+40 신규)
    • Pack 6.7 portfolio 16 + auto-stamp 7
    • Pack 6.8 docgen-placeholders 13
    • CaseDomainType alias 4
  • apps/ops 107 test files (845 tests) 통과
  • 0 lint errors

한 줄 본질 정합

사무소 형사 portfolio (5 죄명 × 9 단계 × 시효) 가시화 + 자동 stamp + 템플릿 spec 으로 변호인 실무 마찰 감소.

본 세션의 모든 변경이 한 줄 본질에 기여:

  1. portfolio 가시화 — 사무소가 N 형사 사건을 한눈에 파악. 어느 단계, 어느 시효, 어느 죄명에 분포하는지 dashboard 가 자동 집계
  2. 자동 stamp — phase 변경 = 일자 입력. 변호인 데이터 capture 마찰 ↓ → 사무소 형사 데이터 quality ↑
  3. docKind 어댑터 — 사무소가 자기 .docx 템플릿 작성·업로드하면 모든 후속 형사 사건의 1-click 생성 활성화 (사무소 학습 자산)
  4. alias 점진 rename — 명명 일반화 + 점진 마이그레이션 안전 path

누적 (2026-05-15~17 전체)

  • 머지 PR 55 + 4 = 59건
  • 8394 web + 845 ops = 9239 테스트 통과
  • 한 줄 본질 핵심 기능 누적:
    • #17: Tenant RAG mock 자가 회귀
    • #18: 사건 분류 + anomaly Phase 3 + production embedding eval (5/5)
    • #19: Gemini classification eval + cron 가이드
    • #20: Pack 6 형사 사건 first slice (14 → 15 종)
    • #21: Pack 6.2 DocKind 22 등재 + CriminalInfoSection + RAG kind chart + exemplar v2
    • #22: Pack 6.4+6.5+6.6 — 9 단계 흐름 + 정밀 시효 + 5 종 죄명 + exemplar cleanup
    • #23: Pack 6.7+6.8 — dashboard portfolio + auto-stamp + docKind 어댑터 + CaseDomainType alias ← Pack 6 portfolio·생성 layer 완성

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (누적 4 세션 잔여)
  2. production Gemini classification baseline 측정 (real tenant 데이터)
  3. 공용 기본 형사 .docx 템플릿 3 종 작성 + Cloud Storage 업로드 (criminal-templates.md 가이드 따라)
  4. generateDocxAction 의 형사 docKind 분기 wiring — isCriminalDocKind 분기 후 buildCriminalDocxRenderData 호출
  5. Pack 6 dashboard widget 의 portfolio chart click → /cases?criminalPhase= 라우트 검증 (filter 사전 적용 동작)
  6. CaseDomainType 점진 sweep — 신규 PR 부터 alias 사용, 누적 호출부 갱신
  7. 형사 사건 portal 노출 정책 — 피해자/피의자 PII 노출 범위 ADR

2026-05-17 후속 #24 — Pack 6 production-ready 5 cap + 정합 cleanup

후속 #23 의 다음 세션 후보 6건 중 자율 모드 적합한 5건 일괄 ship — Pack 6 형사 도메인이 사용자 가시 흐름까지 모두 production. dev hydration · production Gemini baseline 2건은 외부 환경 의존으로 잔여.

머지 PR (5 commit + 1 fix, branch feat/pack6-docgen-wiring-and-pii-adr)

commit분류핵심 변경
Pack 6.9 docgen wiring#2 generateCriminalDocxAction + UI 버튼thin wrapper Server Action (caseId + kind + attorney → buildCriminalDocxRenderData → generateDocxAction 위임). CriminalInfoSection 헤더에 "선임서·의견서·양형 자료" 3 버튼 추가. 다운로드 후 새 탭 시작
Pack 6.7 filter#3 /cases?criminalPhase= 필터RecoveryTypeFilter union 에 형사 5 종 추가. CriminalPhaseFilter 9 단계 신설. CasesListClient 가 URL 인자 hydrate. useCasesData 필터 분기 (legacy phase normalize 포함). CaseItem.recoveryType 19 종 + criminalPhase union 확장
ADR 0046#5 형사 portal PII 정책 proposed3 정책 비교 (A noportal / B redacted / C opt-in). Policy A 권장 — 형사 PII 위험이 민사보다 압도적, 4자리 코드 인증 부적합, 1:1 변호인 채널이 형사 흐름에 더 적합. Pack 6.10 first slice 후속 작업
Pack 6.11 templates#1 공용 docx 템플릿 3 종 자동 생성scripts/generate-criminal-docx-templates.ts — JSZip + OOXML 직접 작성. Malgun Gothic + Title/Heading/Normal 3 스타일. 3 종 .docx (2.4 KB each) → apps/web/public/docxTemplates/. docx-templates createReport 로 sample data 렌더 검증 (placeholder 치환 0 잔존)
Pack 6 packages sweep#4 packages/business-logic sweeprag-eval/types.ts 의 LOCAL RecoveryType 14 종 → CaseDomainType 19 종 (Pack 6 sync) + RecoveryType @deprecated alias. 4 callsite (recovery-settlement · rag-eval/cases · rag-eval/index · types) sweep. apps/ops 62 ref · apps/web ~1700 ref 잔여 (자율 후속 PR)
docs broken-link fixdocusaurus build passcriminal-templates.md 의 /docs/operations/public-template-playbook → 상대 경로

Ship 한 capability

  • 3 형사 docKind 1-click 다운로드 — 변호인이 사건 메타 입력 후 헤더 버튼 한 번으로 docx. 사무소 자체 템플릿 업로드 시 자동 폴백
  • dashboard chart → 필터 link — DashboardCriminalPortfolioCard 의 9 단계 chart 클릭이 실제로 사건 목록을 해당 단계로 필터. legacy phase 자동 normalize
  • ADR 0046 정책 결정 path — 형사 portal 노출이 미정인 잔여 작업을 ADR 로 명시. Policy A (noportal) 권장 + closure path 정의
  • 공용 기본 .docx 3 종 — repo 동봉 + 생성 스크립트 SSoT. 사무소 자체 작업 부담 0
  • packages 형사 5 종 sync — RAG eval 골든 케이스 등록이 형사 사건도 수용 (이전엔 union mismatch 거부)

기술 결정

결정이유
.docx 를 JSZip + OOXML 직접 작성docx npm package 미설치, jszip 만 docx-templates 의 transitive dep. 최소 OOXML (Content_Types · _rels · word/document · styles) 직접 작성으로 외부 의존 0
Policy A (noportal) 권장형사 PII 위험 압도적 + 4자리 코드 인증 부적합. 사용자 피드백 후 점진 확장 path 명시
RecoveryTypeFilter union 에 형사 5 종 추가 vs 별도 type단일 union 으로 dropdown UI 한 곳에서 처리 — 형사·민사 분리 dropdown 보다 단순
CaseDomainType packages 먼저 sweep19 ref 만 — 작고 isolated. apps/ops 62 + apps/web 1700 보다 위험 ↓
script 가 apps/web/public/ 직접 출력Cloud Storage 업로드 (ops) 와 분리 — repo 가 SSoT, Storage 는 cache. 다른 환경 deploy 도 자동 동기화

검증

  • apps/web type-check 통과
  • apps/ops type-check 통과
  • apps/web 706 test files (8394 tests) 통과
  • apps/ops 107 test files (845 tests) 통과
  • 9239 누적 테스트 — drift 회귀 가드 유지
  • docusaurus build 통과 (broken-link fix 포함)
  • docx 렌더 sample — 홍길동·법무법인 너홀로·2026형제45678 정확 치환, {{}} 잔존 0
  • 0 lint errors

한 줄 본질 정합

Pack 6 형사 도메인이 사용자 가시 흐름 (사건 등록 → 단계 입력 → 1-click docx 다운로드 → 다음 사건 사무소 학습) 까지 모두 production.

본 세션의 4 핵심 capability + 1 정합 cleanup 이 모두 한 줄 본질에 직접 기여:

  1. docgen wiring — 변호인이 형사 사건 메타 입력 후 1 클릭으로 docx 받음 = 사무소가 형사 사건 처리 마찰 감소
  2. dashboard filter — portfolio chart → 필터 사건 목록 = 변호인이 단계별 사건 collection 즉시 액세스
  3. 공용 템플릿 — 사무소 자체 작업 0 으로 형사 docx 생성 시작 가능
  4. portal PII ADR — 형사 데이터 노출 정책 결정 path 명시 = production-safe 환경 구축
  5. packages sync — RAG eval 골든 case 가 형사 사건도 학습 자산으로 등록 가능

누적 (2026-05-15~17 전체)

  • 머지 PR 59 + 5 = 64건
  • 9239 누적 테스트 통과
  • 한 줄 본질 핵심 기능 누적:
    • #17~#23 (선행 7 세션)
    • #24: Pack 6 production-ready — docgen wiring + chart filter + ADR 0046 + 공용 docx + packages sync ← Pack 6 사용자 가시 흐름 closure

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (누적 5 세션 잔여 · 외부 환경)
  2. production Gemini classification baseline (real tenant 데이터)
  3. ADR 0046 Policy A 실 구현 (Pack 6.10) — portal 토큰 발급 시 criminal-* 거부 분기 + e2e
  4. CaseDomainType apps/ops 62 ref sweep (다음 자율 후보 — 위험도 ↓)
  5. Pack 6 docKind 렌더 결과 시각 검수 — 변호인이 docx 다운로드 후 한국 법무 양식 적합성
  6. 형사 사건 CriminalInfoSection 변호인 정보 자동 fetch (사무소 마스터 데이터 → attorney form 자동 채움)
  7. CriminalInfoSection 의 9 단계 timeline 클릭으로 단계 jump (현재는 select 만)

2026-05-17 후속 #25 — Pack 6 UX 폴리시 + Policy A ship (4 capability)

후속 #24 의 다음 세션 후보 7건 중 자율 모드 적합한 4건 (#3·#4·#6·#7) 일괄 ship. dev hydration · production Gemini baseline · 시각 검수 3 건은 외부 환경 의존으로 잔여.

머지 PR (4 commit, branch feat/pack6-policy-a-and-ux)

commit분류핵심 변경
Pack 6.10 Policy A#3 ADR 0046 portal 거부createPortalToken 에 recoveryType ∈ criminal-* 거부 분기. PortalLinkDialog 가 props 로 recoveryType 받아 disabled Button "포털 (형사 비노출)" 렌더. 5 죄명 거부 + 민사 통과 + legacy 호환 회귀 가드 3 신규 테스트
Pack 6.10 변호인 자동 fetch#6 CriminalInfoSection attorney 자동getCriminalAttorneyDefaultsAction — tenant 마스터 데이터 우선순위 fetch (criminalDefaults > tenantName > empty). handleGenerate 가 defaults 받아 generateCriminalDocxAction.attorney 에 전달. 매번 input 부담 0
Pack 6.10 timeline jump#7 9 단계 click 시 phase jumpPhaseTimeline 각 segment 가 button 으로 변경 + onJump callback. handleJumpPhase — read 모드 즉시 저장 (autoStamp 일자 동시) · edit 모드 form sync. animate-pulse + "…" 라벨로 진행 시각 신호
ops sweep#4 apps/ops CaseDomainType sweeprun-add-rag-eval-case-scenario.ts · AddRagEvalCaseScenarioCard.tsx — local clone 14 → 19 종 (Pack 6 형사 5 추가). RecoveryType → CaseDomainType type rename. 이전 ops 시나리오에서 형사 골든 케이스 등록 거부되던 결함 해소

Ship 한 capability

  • 형사 portal defense-in-depth 차단 — 서버 (createPortalToken) + UI (PortalLinkDialog disabled) 양쪽. 변호인이 실수로 형사 사건 토큰 발급 시도해도 거부
  • 변호인 정보 마찰 0 — 사무소 setup 시 tenantName 만 입력해도 attorneyName 자동 사용. criminalDefaults 설정 시 형사 전용 프로필 사용
  • timeline = action surface — read 모드의 9 단계 timeline 이 단순 viewing 에서 액션 가능 컨트롤로. 변호인이 사건 진척을 timeline 1 클릭으로 완료
  • ops 골든 케이스 형사 수용 — RAG eval 골든 셋이 Pack 1~6 19 종 모두 등록 가능

기술 결정

결정이유
Policy A 서버 + UI 양쪽 차단 (defense-in-depth)UI 만 disabled 면 직접 Server Action 호출로 우회 가능. 패키지 함수에 검사 추가로 모든 경로 차단
PortalLinkDialog props.recoveryType 옵셔널기존 호출부 (Pack 1~5) 호환 — recoveryType 미전달 시 정상 dialog 동작
getCriminalAttorneyDefaults 우선순위 (criminalDefaults > tenantName > empty)사무소가 별도 형사 프로필 설정 안 했어도 정상 동작 (tenantName fallback). source 필드로 fetch 경로 노출 — debugging 가능
timeline click = 즉시 저장 (read 모드)변호인 워크플로: timeline 보다가 단계 진척 클릭 — 추가 confirm 모달 없이 즉시 commit + toast 안내. 잘못 클릭 시 이전 단계 다시 클릭으로 되돌릴 수 있음
Edit 모드 timeline click = form 변경만사용자가 편집 중일 때는 timeline click 도 form-only — 저장 버튼이 single commit point
ops local clone 명시적 syncapps/* 간 import 금지로 ops 가 자체 enum 필요. 14 → 19 종 명시 갱신 (ADR 0028 alias 사용 불가 — packages 의 alias 도 ops 입장에선 동일 cost)

검증

  • apps/web type-check 통과
  • apps/ops type-check 통과
  • apps/web 706 test files (8397 tests) 통과 (+3 신규 Policy A)
  • apps/ops 107 test files (845 tests) 통과
  • 0 lint errors

한 줄 본질 정합

Pack 6 형사 도메인이 보안 (portal 거부) + UX 마찰 (변호인 자동 fetch + timeline 직접 액션) 면에서 production polish.

본 세션의 4 capability 모두 한 줄 본질의 핵심 보강:

  1. Policy A — 사무소 데이터 (형사 PII) 가 의뢰인 외부로 누출되지 않는 default-safe 보안 layer. 한 줄 본질 의 "자기 데이터" 가 사무소 내부에 머무름을 보장
  2. 변호인 자동 fetch — 사무소가 변호인 정보 매번 입력하지 않아도 docx 생성 — 데이터 입력 마찰이 학습 자산 누적 속도 ↑
  3. timeline jump — 변호인이 사건 진척을 즉시 stamp — 사무소 형사 portfolio 데이터 quality ↑
  4. ops sync — RAG eval 골든 셋이 형사 사건도 학습 자산으로 검증 — 사무소 AI 학습 회귀 측정 surface 가 19 종 전체 cover

누적 (2026-05-15~17 전체)

  • 머지 PR 64 + 4 = 68건
  • 9242 누적 테스트 통과 (web 8397 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#24 (선행 8 세션)
    • #25: Pack 6 UX polish + Policy A ← 형사 도메인 보안·UX 표면 정착

다음 세션 후보

  1. dev cold restart 후 hydration 결함 시각 재확인 (누적 6 세션 잔여 · 외부)
  2. production Gemini classification baseline (real tenant 데이터)
  3. Pack 6 docKind 렌더 결과 시각 검수 (변호인 1:1 review · 외부)
  4. 사무소 settings 에 criminalDefaults 편집 UI (Pack 6.12) — attorneyName/address/number 사무소 단위 설정
  5. useTenant Provider 가 criminalDefaults 도 expose (client cache · refresh 시 1 fetch 절감)
  6. CaseDomainType apps/web ~1700 ref 점진 sweep (다음 자율 후보)
  7. timeline jump 의 backwards click (예: trial-first → investigation) 사용자 confirm 모달 (실수 보호) → v1 호환 필드 제거

2026-05-17 후속 #26 — Pack 6.12 사무소 설정 + UX 정밀화 (4 capability)

후속 #25 의 다음 세션 후보 7 건 중 자율 가능 4건 (#4 + #5 묶음, #6, #7) 일괄 ship. 외부 환경 의존 3 건 (#1, #2, #3) 잔여.

머지 PR (3 commit + 1 sweep)

commit분류핵심 변경
Pack 6.12 settings + cache#4+#5 형사 변호인 기본 프로필 + TenantProvider 캐시saveCriminalDefaultsAction + CriminalDefaultsSection (owner only · 길이 검증 · 빈 값 FieldValue.delete). (workspace)/layout.tsx 가 tenant fetch 시 criminalDefaults 도 읽어 TenantProvider context 캐시. CriminalInfoSection 이 useTenant() 로 캐시 사용 — 매 다운로드마다 호출되던 getCriminalAttorneyDefaultsAction 1 회 절감
Pack 6.12 backward confirm#7 backward jump AlertDialogPhaseTimeline click 이 backward (현재 → 이전 단계) 인 경우 AlertDialog 확인 모달. Forward 클릭은 그대로 즉시 commit (자연스러운 워크플로). commitPhaseJump 함수 분리 — 모달 확인 후 호출
CaseDomainType sweep #3#6 apps/web partial sweepcriminal-portfolio.ts (Pack 6.7) + set-recovery-type-action.ts type identifier 만 RecoveryType → CaseDomainType. function 이름 + log 라벨 유지 (callsite 호환)

Ship 한 capability

  • 사무소 단위 형사 변호인 프로필 — owner 가 settings 에서 1 회 입력하면 모든 형사 사건 자동 적용. 매 사건 마다 wizard 가 attorney 묻지 않음
  • TenantProvider context 캐시 — layout SSR 시 1 fetch (logoUrl 과 동일 snapshot 활용). client 컴포넌트는 useTenant() 한 줄로 즉시 사용. Server Action 절감 (3 docKind 클릭 시 3 → 0)
  • backward jump 실수 보호 — Forward 는 매끄럽게, backward 는 명시적 confirm. 실수로 phase 되돌리는 사고 차단
  • 점진 sweep 3 차 — packages (session #24) + ops (session #24) + web partial (이번 세션) 누적

기술 결정

결정이유
layout.tsx 에 criminalDefaults fetch 합치기이미 logoUrl 위해 tenant doc 조회 중 — 같은 snapshot 에서 한 번에 읽으면 fetch 0 비용 추가
useTenant().criminalDefaults 옵셔널설정 미입력 사무소 호환 (undefined). 기존 호출부 (Pack 1~5) 영향 0
FieldValue.delete() 빈 값 처리Firestore 에 "" 저장 안 함 — undefined vs "" 분기 모호함 회피
Forward 즉시 commit · Backward 만 confirm변호인의 자연 워크플로 (다음 단계 진척) 는 마찰 0, 실수 발생할 만한 동작 (역방향) 만 명시 confirm
점진 sweep — 함수 이름 유지RecoveryTypeControls / setCaseRecoveryTypeAction 같은 callsite 의존 식별자는 보존. type 식별자만 rename — diff 최소화

검증

  • apps/web type-check 통과
  • apps/web 706 test files (8397 tests) 통과
  • 0 lint errors

한 줄 본질 정합

사무소 형사 도메인 운영 마찰 ↓ + 실수 보호 layer + 명명 점진 정착.

본 세션 4 commit 모두 사무소가 형사 사건을 더 빠르고 안전하게 처리하도록:

  1. criminalDefaults settings — 사무소가 형사 변호인 정보 1회 입력하면 모든 후속 사건 자동 적용 = 변호인 데이터 capture 마찰 ↓
  2. TenantProvider cache — 매 docgen 클릭마다 Server Action 절감 = response time ↓
  3. backward confirm — 실수로 단계 되돌리는 사고 방어 = 데이터 quality ↑
  4. partial sweep — Pack 6 형사 5 종 추가 후 명명이 자연스러워지는 path

누적 (2026-05-15~17 전체)

  • 머지 PR 72 + 4 = 76건
  • 9242 누적 테스트 통과 (web 8397 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#25 (선행 9 세션)
    • #26: Pack 6.12 사무소 설정 + UX 정밀화 + sweep #3 ← Pack 6 운영 안정 layer

다음 세션 후보

  1. dev cold restart hydration · production Gemini baseline · 시각 검수 (외부 환경 3 건 누적)
  2. CaseDomainType apps/web ~1700 ref 자동화 sweep (codemod / sed 기반)
  3. CriminalDefaultsSection 의 e2e — owner 권한 / staff 권한 / 빈 입력 시나리오
  4. timeline forward click 시 1-tap 단계 진척 UX 검증 (e2e)
  5. Pack 6 의 portal 사이드바 hide — 의뢰인 portal 이 형사 사건 자체 404 처리 (ADR 0046 Policy A 후속 layer)
  6. 형사 사건 case-flow status badge — 9 단계 → 6 단계 case-flow SSoT mapping
  7. CriminalInfoSection 의 변호사 본인 (session.name) vs criminalDefaults 분리 — 사무소 대표 vs 담당 변호사

2026-05-17 후속 #27 — Pack 6.13 Policy A 도착 layer + case-flow 매핑 + 단위 가드 (4 capability)

후속 #26 의 다음 세션 후보 7 건 중 자율 가능 4건 (#5 → portal layer / #6 → case-flow / #3 → CriminalDefaults 단위 / #2 → sweep 추가) 일괄 ship. 외부 환경 의존 3 건 (#1·#4 e2e·시각 검수) 잔여.

머지 PR (4 commit, branch feat/pack6-portal-hide-and-flow)

commit분류핵심 변경
Pack 6 portal layer#5 ADR 0046 Policy A 도착 시점 차단validateTokenAction 에 case doc fetch + criminal-* 거부 분기. defense-in-depth 2 layer (발급 + 사용). legacy 토큰 / 사후 recoveryType 변경 / 발급 우회 시도 모두 차단. fail-safe close (case 조회 실패 시 거부). 3 신규 테스트
Pack 6.13 case-flow 매핑#6 9 단계 → 5 단계 case-flow statusmapCriminalPhaseToStatus pure function — 변호인 실무 시각 매핑 (defense-appointed→소제기, investigation~appeal→진행중, supreme-appeal→판결대기, finalized→종결, enforced→집행중). CriminalInfoSection 헤더에 STATUS_STYLE 재사용 badge 추가. 7 신규 테스트
CriminalDefaults 단위#3 validate 순수 함수 분리 + 13 단위 테스트settings/_lib/criminal-defaults-validate.ts pure function. settings/_actions 가 inline validate 제거하고 import. 빈 문자열 허용 / null·undefined·string 거부 / 3 boundary inclusive 통과 검증
CaseDomainType sweep #4#2 점진 sweep — icon-map + statute-of-limitationstype identifier 만 RecoveryType → CaseDomainType (function 이름 + 합성 식별자 보존). case-recovery-type.ts sed 충돌로 revert — function name resolveCaseRecoveryType 보호

Ship 한 capability

  • portal Policy A 2 layer 차단 — 발급(#2355)+사용(이번) 두 시점 모두 criminal-* 거부. legacy 토큰 + 사후 변경 + 우회 시도 모두 보호
  • case-flow 일관성 — 형사 사건이 dashboard "사건 단계 분포" 등 공용 위젯과 동일 status badge 사용 가능. 9 단계 phase 의 진행도가 5 단계 status 로 자연 mapping
  • CriminalDefaults 회귀 가드 — Server Action 검증 로직 분리 + 13 단위 테스트. mock 없이 validation 회귀 자동 catch
  • 점진 sweep 4 차 — 누적 4 sweep (packages 19, ops 62, web partial #1 7, web partial #2 9 ref)

기술 결정

결정이유
validate 시점에 case fetch토큰 발급 시 ✓ + 사용 시 ✓ defense-in-depth. fail-safe close 로 일시 장애 시 안전 우선
mapCriminalPhaseToStatus pure functionUI badge 외 향후 dashboard 분포 widget 등 재사용 가능. exhaustive switch — Pack 6 phase 추가 시 빌드 타임 catch
STATUS_STYLE 재사용형사 status badge 가 민사와 시각적으로 동일 — case-flow 단일 surface 유지
validate function 분리 후 export type aliascallsite 호환 (CriminalDefaultsPayload import 경로 동일)
case-recovery-type.ts sed revertfunction name resolveCaseRecoveryType 충돌 — 안전한 sweep 만 commit (sed regex 한계)

검증

  • apps/web type-check 통과
  • apps/web 707 test files (8420 tests) 통과 (+23 신규 — Policy A 3 + case-flow 매핑 7 + validate 13)
  • 0 lint errors

한 줄 본질 정합

사무소 형사 도메인 보안 (2 layer) + 도메인 일관성 (case-flow) + 회귀 가드 (단위 테스트) 강화.

본 세션 4 capability 모두 한 줄 본질 운영 layer 보강:

  1. portal 2 layer — 사무소 형사 PII 가 의뢰인 portal 로 누출되지 않음을 발급+사용 시점 모두 보장
  2. case-flow 매핑 — 형사 사건도 dashboard·portfolio·status 분포 위젯에서 다른 도메인과 일관된 surface
  3. validate 분리 — 검증 로직 회귀 위험 ↓ — 향후 Pack 6.X 도메인 확장 시 안전 path
  4. 점진 sweep — 명명 정착 안정성 — 신규 PR 이 새 이름 사용하는 기준 marker 누적

누적 (2026-05-15~17 전체)

  • 머지 PR 76 + 4 = 80건
  • 9265 누적 테스트 통과 (web 8420 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#26 (선행 10 세션)
    • #27: Pack 6.13 Policy A 2 layer + case-flow 매핑 + 단위 가드 ← Pack 6 운영 안정 layer 정착

다음 세션 후보

  1. dev cold restart hydration · production Gemini baseline · 시각 검수 (외부 환경 3 건 누적)
  2. e2e Policy A — 형사 사건 발급 거부 + portal 도착 거부 시나리오 (외부 환경)
  3. e2e CriminalDefaultsSection — owner 입력·staff 차단·empty 시나리오 (외부 환경)
  4. dashboard "사건 단계 분포" 위젯에 Pack 6 형사 사건도 카운트 (case-flow 매핑 활용)
  5. CaseDomainType apps/web 잔여 30 파일 자동화 sweep (codemod 도구)
  6. 형사 사건 case-flow 진행률 시각화 widget — overview 탭 별도 카드
  7. ADR 0046 후속 — Policy B (redacted portal) 또는 C (opt-in) 의 사용자 피드백 baseline 측정 가이드

2026-05-17 후속 #28 — Pack 6.14 dashboard 통합 + sweep 5 차 + ADR 0047 (3 capability)

자율 모드 — 후속 #27 의 다음 세션 후보 7건 중 자율 가능 3건 일괄 ship. 외부 환경 4건 잔여.

머지 PR (3 commit, branch feat/pack6-dashboard-flow-widget)

commit분류핵심 변경
Pack 6.14 dashboard#1 case-flow distribution 형사 통합inferCaseFlowStage 에 criminalPhase 시그널 + mapCriminalPhaseToFlow pure 매핑 (9 → 6 단계). CaseFlowDistributionCard 가 d.criminalPhase 전달 → dashboard "사건 단계 분포" 위젯이 민사+형사 통합 카운트. 12 신규 단위 테스트
sweep 5 차#5 perl word boundary sweep12 추가 파일 RecoveryType → CaseDomainType (lib · _recovery · _tests). function name + 합성 식별자 모두 보존
ADR 0047#4 Policy 진화 baselinePack 6.10 (Policy A) 의 6개월 운영 후 Policy B/C 채택 평가 기준. 3 측정 항목 + 결정 트리 + B/C 구현 가이드

Ship 한 capability

  • dashboard 형사 사건 통합 — CaseFlowDistributionCard 가 9 단계 형사 phase 도 6 단계 case-flow 로 mapping → 단일 위젯에서 민사+형사 portfolio 한눈 (회수 사무소·형사 사무소 모두 활용)
  • 명명 정착 누적 진척 — packages 19 + ops 62 + web (sweep #1~5) ~50 ref 자율 마이그레이션
  • Policy A 평가 path — 사용자 피드백 baseline 정의로 ADR 0046 의 "6개월 후 평가" closure path 명시

기술 결정

결정이유
criminalPhase 우선 매핑 (다른 휴리스틱 무시)형사 사건은 hearingCount·judgmentDate 등 일반 시그널과 의미 다름. phase 자체가 SSoT
9 → 6 매핑 (변호인 워크플로)case-flow.md SSoT 의 의미 보존 — 분류/서류/제출/재판/결과/집행
perl negative lookbehind sweepfunction name (resolveCaseRecoveryType) + 합성 식별자 보존. BSD sed 한계 우회
Policy B/C 구현 보류 (ADR draft)production 측정 데이터 없으면 채택 근거 모호 — measurement-first

검증

  • apps/web type-check 통과
  • apps/web 707 test files (8432 tests) 통과 (+12 신규)
  • 0 lint errors
  • docusaurus build 통과 (ADR 0047 포함)

한 줄 본질 정합

Pack 6 형사 도메인이 dashboard 통합 표면 + 명명 정착 + 정책 진화 path 까지 layer 안정.

본 세션의 3 capability 모두 사무소 운영 surface 의 일관성·진화 path 강화:

  1. dashboard 통합 — 형사 사무소도 case-flow 위젯 활용 가능 (이전엔 형사 사건이 별도 위젯 only)
  2. sweep 진척 — 신규 PR 이 새 이름 사용하는 누적 marker. 향후 ADR 0028 closure 의 베이스
  3. ADR 0047 — 미래 policy 결정에 측정 데이터 기반 평가 path 명시

누적 (2026-05-15~17 전체)

  • 머지 PR 80 + 3 = 83건 (이번 세션은 squash 1)
  • 9277 누적 테스트 통과 (web 8432 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#27 (선행 11 세션)
    • #28: dashboard 형사 통합 + sweep 5 + ADR 0047 ← Pack 6 표면 정합 + 진화 path

다음 세션 후보

  1. ops dashboard 의 Pack 6 portal 측정 위젯 (ADR 0047 자동 수집 Pack 6.16)
  2. case-flow distribution chart 의 형사 case 클릭 → /cases?recoveryType=criminal-* filter
  3. CaseDomainType apps/web 잔여 ~15 파일 sweep 6 차
  4. 형사 사건 단계 별 elapsed days 텔레메트리 (변호인 portfolio 시각)
  5. 외부 환경 의존 누적 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-17 후속 #29 — Pack 6.15 + 6.16 + sweep 6 차 (3 capability)

자율 모드 — 후속 #28 의 다음 세션 후보 5건 중 자율 가능 3건 ship. 외부 환경 1 + ops 위젯 1 잔여.

머지 PR (3 commit, branch feat/pack6-sweep6-and-elapsed)

commit분류핵심 변경
sweep 6 차CaseDomainType 20 추가 파일 마이그레이션perl word boundary 로 lib · _recovery · _tests · legacy/v2 (20 파일). compatibility 문제로 recovery-input-schemas.ts · new/_components revert
Pack 6.15 chart click filter#2 case-flow distribution row click → /cases?caseFlowStage=XCaseFlowStageFilter 9 단계 union + CaseFilterState.caseFlowStage. CasesListClient hydrate + useCasesData filter (inferCaseFlowStage 동일 알고리즘). CaseFlowDistributionCard 각 row Link wrap
Pack 6.16 elapsed days#4 단계별 경과일 텔레메트리computeCriminalElapsed pure function — totalDays · daysAtCurrentPhase · daysSinceIndictment. ElapsedRow 컴포넌트 — 90 일+ amber 강조. 8 신규 단위 테스트

Ship 한 capability

  • 누적 ~150 ref 명명 마이그레이션 — packages 19 + ops 62 + web sweep #1~#6 ≈ 70
  • dashboard → 사건 목록 single click filter — 변호인이 단계 row 1 클릭으로 해당 단계 사건 목록 즉시 액세스 (Pack 6 형사 + Pack 1~5 민사 동일 UX)
  • stuck 패턴 시각 — 변호인이 사건이 같은 단계에 90 일+ 머무는 것 즉시 catch. portfolio 시각의 "처리 속도" baseline

기술 결정

결정이유
sweep revert 일부recovery-input-schemas.ts 의 CaseDomainType export alias 자체 충돌 + Step1RecoveryType filename callsite 의존. 부분 revert 로 안정 우선
useCasesData 의 caseFlowStage 분기에서 inferCaseFlowStage 재호출CaseFlow 위젯과 동일 알고리즘 보장 (drift 0). 200 case 한도 성능 영향 미미
90 일 stuck threshold형사 사건 단계 평균 처리 일수의 보수적 임계 — production 데이터 누적 후 조정 후보
ElapsedRow 일자 모두 null 시 자체 hide새 등록 사건 / 미입력 케이스 시각 노이즈 회피

검증

  • apps/web type-check 통과
  • apps/web 707 test files (8440 tests) 통과 (+8 신규)
  • 0 lint errors

한 줄 본질 정합

Pack 6 형사 운영 시각 강화 (chart filter · stuck pattern) + 명명 정착 누적.

본 세션 3 capability 모두 한 줄 본질의 운영 표면:

  1. chart filter — 변호인이 사무소 portfolio 를 single click 으로 detailed list 액세스 가능
  2. elapsed days — 사무소 "처리 속도" baseline. 향후 production 데이터 누적 시 stuck pattern 자동 detection
  3. sweep 6 차 — Pack 6 + ADR 0028 명명 정착 marker

누적 (2026-05-15~17 전체)

  • 머지 PR 83 + 3 = 86건 (squash 1)
  • 9285 누적 테스트 통과 (web 8440 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#28 (선행 12 세션)
    • #29: chart filter + elapsed days + sweep 6 ← Pack 6 portfolio 시각 UX 정합

다음 세션 후보

  1. ops dashboard 의 Pack 6 portal 측정 위젯 (ADR 0047 활동 로그 type=portal_token_blocked_criminal 신설 + 자동 수집 Pack 6.17)
  2. CriminalInfoSection elapsed days 의 production tenant 데이터 baseline (외부)
  3. case-flow chart click 의 e2e (외부)
  4. CaseDomainType apps/web 잔여 ~5 파일 sweep 7 차 (recovery-input-schemas 본체 외)
  5. 외부 환경 의존 누적 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-17 후속 #30 — Pack 6.17 activity log + 6.18 ops 위젯 (2 capability)

자율 모드 — 후속 #29 의 다음 세션 후보 5건 중 자율 가능 2건 ship (큰 비중). 외부 환경 3건 잔여.

머지 PR (2 commit, branch feat/pack6-ops-portal-metrics)

commit분류핵심 변경
Pack 6.17 activity typeportal_token_blocked_criminal 신설ActivityType union + writeActivityLog 호출 (workspace · portal 양쪽). logCriminalPortalBlock helper 분리 (200줄 invariant 보호). ActivityLogClient label/tone + activity-notification-bridge 매핑
Pack 6.18 ops 위젯dashboard 형사 portal 거부 측정Pack6PortalBlockedCard — collectionGroup 30일 누적 + 발급/사용 분기 + top 5 tenants. 활동 0 건 자체 hide. ADR 0047 baseline 자동 수집

Ship 한 capability

  • ADR 0046 Policy A 텔레메트리 — 발급+사용 시점 거부가 활동 로그로 영구 기록. 의뢰인 알림은 보내지 않음 (audit only)
  • ops baseline 자동 수집 — ADR 0047 의 6 개월 평가 측정이 production 부터 누적 시작. 운영자가 dashboard 에서 즉시 확인
  • 명명 누적 진척 — sweep 7 차 검토 (대부분 function name + 식별자로 자연 보호, 9 파일만 type 임포트 잔여)

기술 결정

결정이유
logCriminalPortalBlock helper 분리200줄 baseline invariant 통과 + 두 호출부 동일 로직 sync
activity log type 신설 vs metadata 분기운영 dashboard 가 type filter 로 즉시 count — metadata 검색은 collectionGroup 성능 ↓
활동 0 건 자체 hide대부분 사무소 (비형사) 노이즈 회피. Pack 6 도입 사무소만 위젯 노출
activity-notification-bridge: null의뢰인에게 거부 사실 알림 발송 안 함 (PII 안전)

검증

  • apps/web type-check + 707 tests (8440) 통과
  • apps/ops type-check + 107 tests (845) 통과
  • 0 lint errors
  • server-action 200줄 baseline 갱신 (portal-token-actions 212)

한 줄 본질 정합

형사 PII 보호 ↑ + 정책 진화 측정 자동화 + 명명 정착 누적.

본 세션 2 commit 모두 한 줄 본질의 운영 layer:

  1. activity log telemetry — 사무소 정책 효과를 데이터로 측정 (ADR 0047 결정 트리 자동 입력)
  2. ops 측정 위젯 — 운영자가 production 신호를 실시간 확인 (수동 sample 0)

누적 (2026-05-15~17 전체)

  • 머지 PR 86 + 2 = 88건 (squash 1)
  • 9285 누적 테스트 통과
  • 한 줄 본질 핵심 기능 누적:
    • #17~#29 (선행 13 세션)
    • #30: activity log telemetry + ops 위젯 ← Pack 6 정책 진화 측정 자동화

다음 세션 후보

  1. ops Pack 6 위젯의 e2e + 활동 로그 시드 (외부 환경)
  2. 사무소 dashboard 의 "Pack 6 portal 거부" 카운트 표시 (workspace 측 mirror)
  3. CaseDomainType sweep 8 차 — lib/cases/schemas.ts re-export 확장 + 9 잔여 파일
  4. case-flow 의 "stuck pattern" 자동 anomaly 가설 trigger (ADR 0042 통합 baseline)
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #31 — Pack 6.19 stuck count + 6.20 anomaly trigger + sweep 8 (3 capability)

자율 모드 — 후속 #30 의 다음 세션 후보 5건 중 자율 가능 3건 ship.

머지 PR (3 commit, branch feat/pack6-mirror-and-stuck-trigger)

commit분류핵심 변경
Pack 6.19 stuck countportfolio stuck 사건 카운트computeCriminalPortfolio.stuckCount + DashboardCriminalPortfolioCard 의 amber chip "stuck N (90일+)". 5 신규 단위 테스트 (90 임계 inclusive + finalized 제외 + 분포)
sweep 8 차schemas.ts Pack 6 sync + CaseDomainType aliaslib/cases/schemas.ts 14 → 19 종 RECOVERY_TYPE_VALUES (Pack 6 형사 5 추가). NON_DEBT_RECOVERY_TYPES 8 → 13. CaseDomainType + CASE_DOMAIN_TYPE_VALUES alias 신설. types/case.ts CasePayload union 동기화
Pack 6.20 anomaly triggerADR 0042 stuck 시그널 통합criminalStuckSignal schema + readCriminalStuckSignal collector + classifyCriminalStuckStatus + prompt-builder formatSignalLine/extractAnomalyKeywords. LLM 가설 자동 trigger (30%+ red · 15~30% yellow). 9 신규 단위 테스트

Ship 한 capability

  • stuck pattern 3 층 모니터링 — Pack 6.16 (사건 단위 elapsed) + 6.19 (portfolio chip) + 6.20 (anomaly LLM 가설). 변호인 시각 + 사무소 portfolio 시각 + 운영 anomaly catch
  • schemas Pack 6 sync — 신규 사건 wizard Step3 가 형사 5 종 정상 수용 (이전 silent skip 위험 해소)
  • 명명 정착 누적 진척 — packages 19 + ops 62 + web sweep #1~#8 ≈ 90+ ref 마이그레이션

기술 결정

결정이유
stuckRatio 30/15% 임계보수적 시작점. ADR 0047 baseline 같이 production 측정 후 조정
ADR 0042 signal collector 에 통합LLM 가설 자동 trigger — 운영자가 수동 검사 불필요
finalized/enforced 제외종결 사건은 stuck 무관 (재판 종결 = 정상 진행)
classifyCriminalStuckStatus purebootstrap 분류로 형사 미운영 사무소 noise 제거

검증

  • apps/web type-check + 707 test files (8469 tests) 통과 (+14 누적)
  • 0 lint errors

한 줄 본질 정합

사무소 형사 portfolio 의 "처리 속도" anomaly 가 LLM 가설로 자동 surface.

본 세션 3 capability 모두 anomaly 자동화 closed-loop 강화:

  1. stuck count — portfolio 수준 시그널 (사무소가 사건이 stuck 됐는지 한눈에)
  2. schemas sync — Pack 6 데이터 무결성 (wizard 누락 fix)
  3. anomaly trigger — operations layer 자동화 (운영자 부담 ↓ · 사무소 운영 anomaly 자동 detect)

누적 (2026-05-15~18 전체)

  • 머지 PR 88 + 3 = 91건 (squash 1)
  • 9314 누적 테스트 통과 (web 8469 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#30 (선행 14 세션)
    • #31: stuck pattern 3 층 monitoring + anomaly LLM trigger + schemas sync ← Pack 6 운영 anomaly closed-loop

다음 세션 후보

  1. Pack 6 형사 사건 별도 시드 fixture (tenant-fixture page 의 1 클릭 시드 옵션)
  2. CriminalDefaultsSection production 검증 e2e (외부 환경)
  3. Pack 6.21 — 형사 사건 timeline 9 단계 별 ETA 산출 (사무소 별 평균 처리 일수)
  4. CaseDomainType sweep 9 차 — recovery-input-schemas 본체 (CaseDomainType primary, RecoveryType deprecated)
  5. 외부 환경 의존 5건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #32 — Pack 6 형사 시드 fixture + anomaly summary 통합 (1.5 capability)

자율 모드 — 후속 #31 의 다음 세션 후보 5건 중 자율 가능 1건 + 부수 fix 1건 ship.

머지 PR (1 commit, branch feat/pack6-seed-and-eta)

commit분류핵심 변경
Pack 6 시드 fixture#1 ops 1 클릭 시드 + signalToSummary 통합seed-criminal-portfolio-mock-action.ts — 사기 3 + 횡령 2 + 폭행 1 (가중·구속·시효임박·stuck 다양 분포). UI 추가 (tenant-fixture page red 강조 섹션). anomaly-hypothesis-helpers.ts 의 signalToSummary 가 criminalStuck case 추가 (sourceMetric=criminalStuck.ratio)

Ship 한 capability

  • Pack 6 emulator dev path — 형사 사건 6 건 1 클릭으로 dashboard + ops 위젯 + anomaly 가설 모두 검증 가능. tenant-fixture page 에 Anomaly mock 와 같은 UX 패턴 통합
  • anomaly summary 완성 — signalToSummary 가 4 source 모두 cover (ragMergeQuality + docgenStats + draftDiffs + criminalStuck). 가설 카드 표시 시 criminalStuck 도 일관

기술 결정

결정이유
시드 사건 6 건 mix모든 alert chip + stuck pattern + anomaly trigger 검증할 수 있는 최소 분포
signalToSummary 누락 분기 채움Pack 6.20 signal 추가 후 helper 가 noReturn 컴파일 에러로 노출 — 4 case discriminated union exhaustive 강제
sweep 9 차 skipalias 상태 이미 최적 — RecoveryType ↔ CaseDomainType 양방향 호환 + neue 코드는 새 이름 사용
ETA 산출 보류9 단계 평균 처리 일수는 사무소 별 데이터 누적이 필요한 baseline. Pack 6.20 anomaly trigger 가 stuck pattern 으로 이미 동일 신호 cover. 별도 위젯의 가치 명확하지 않아 보류

검증

  • apps/ops type-check + 107 test files (845 tests) 통과
  • apps/web 무관 회귀 0

한 줄 본질 정합

Pack 6 형사 도메인 production-ready validation 자동화 — dev path 마찰 0 + anomaly summary 일관성.

본 세션 1 capability 가 사무소 운영 검증 surface 보강:

  1. dev path 시드 — production 검증 없이 모든 Pack 6 UX 검증 가능
  2. summary 통합 — Pack 6.20 anomaly trigger 가 LLM 가설 layer 까지 완전히 통합 (sourceMetric=criminalStuck.ratio 가 hypothesis.signals 에 정상 표시)

누적 (2026-05-15~18 전체)

  • 머지 PR 91 + 1 = 92건 (squash)
  • 9314 누적 테스트 통과 (web 8469 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#31 (선행 15 세션)
    • #32: Pack 6 시드 fixture + anomaly summary 통합 ← Pack 6 dev validation 표면

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출 — 사무소 별 historical 데이터 baseline 후 추가
  3. CaseDomainType apps/web 잔여 ~9 파일 sweep — recovery-input-schemas alias swap (RecoveryType deprecated 표시)
  4. Pack 6.22 — anomalyHypothesis 카드의 criminalStuck source 별 추천 action ("부담 변호인 추가" 등)
  5. 외부 환경 의존 5건

2026-05-18 후속 #33 — Pack 6.22 anomaly action library + sweep 9 canonical swap (2 capability)

자율 모드 — 후속 #32 의 다음 세션 후보 5건 중 자율 가능 2건 (#3 sweep 9 · #4 Pack 6.22) 일괄 ship. 외부 환경 의존 3 건 잔여.

머지 PR (2 commit, branch feat/pack6-anomaly-actions-sweep9)

commit분류핵심 변경
Pack 6.22 anomaly action library#1 LLM + curated 액션 mergepackages/business-logic/src/ops-anomaly/suggested-actions.ts (NEW) — suggestedActionsForSource(source, status) 순수 함수 라이브러리. criminalStuck red → 3 액션 (stuck 검토 · 변호인 분담 · 인력 보강), yellow → 1 액션 (progress jump). ragMergeQuality / docgenStats / draftDiffs 도 status 별 1 액션. mergeSuggestedActions(llm, suggested, max=5) 가 LLM 우선 + 중복 label 제거 + max cap. generateAnomalyHypothesisAction 가 LLM proposedActions + curated merge → Firestore 저장. 12 unit tests
ADR 0028 sweep 9 — canonical swap#2 RecoveryType → CaseDomainType 정식 승격두 canonical 파일 (apps/web/lib/cases/schemas.ts + recovery-input-schemas.ts) 의 canonical 을 CASE_DOMAIN_TYPES / CaseDomainType 으로 swap. RECOVERY_TYPES / RecoveryType / RECOVERY_TYPE_LABEL / RecoveryTypeSchema 는 alias 로 보존 + @deprecated JSDoc (IDE 경고). drift 가드 신설 — case-domain-type-parity.test.ts 19 종 순서·내용 + alias referentially 검증 (7 tests). 1785+ 참조 호출부 동작 무변화

Ship 한 capability

  • anomaly LLM 카드 행동 가능 보장 — LLM 응답에 source-specific 액션 누락 시 curated 라이브러리가 자동 보강. criminalStuck red 가설 카드에서 변호사가 즉시 액션 가능 (사건 목록 검토 → /cases?caseFlowStage=5 직링크 + 분담 검토 + 인력 보강). 4 source × 2 status 매트릭스 cover
  • CaseDomainType naming 정식 승격 — Pack 1 시점 명명 (RecoveryType) 이 Pack 1~6 19 종 도메인 전체로 일반화된 의미를 IDE 가 가르치게 됨. @deprecated 가 신규 코드의 자연스러운 migration 유도. drift 가드가 sweep 회귀 차단

기술 결정

결정이유
curated 액션은 pure function library 분리LLM 응답이 source 별 액션 누락 시 보강 — ops-anomaly 패키지에 두면 generate-anomaly-hypothesis-action.ts + future ops UI 모두 재사용. PR-B6 server action 의 helper 책임 분리
LLM 액션을 우선시키고 curated 는 fallbackLLM 은 시그널 context 보고 더 구체적 액션 생성 가능. curated 는 그 source 의 minimum-viable 액션 보장
max cap 5 적용카드 UI 가 5 개 액션 이상 표시하면 운영자 cognitive load 폭증. 중복 dedup 도 일관 라벨 가정
scenarioCardId 의무 Xcurated 일부에만 부착 (case-flow-stuck-review · rag-self-regression-run). LLM 이 자유롭게 scenarioCardId 제안 가능하도록 자리 남김
canonical swap 실시 (RecoveryType alias 보존)1785+ 참조 호출부 break 비용 회피 — alias referentially 동일하므로 동작 0 변화. IDE @deprecated 가 점진 sweep 유도
drift 가드 추가두 canonical 파일이 같은 19 종 정의를 별도 const 로 유지 — drift 시 silent 회귀 위험 (wizard Step1 schema 가 schemas.ts 사용, 나머지 도메인 입력은 recovery-input-schemas.ts 사용). parity test 가 순서·라벨 ·alias 동등성 모두 강제

검증

  • apps/web type-check + 708 test files (8481 tests) 통과
  • apps/ops type-check + 107 test files (845 tests) 통과
  • 신규 12 + 7 = 19 단위 테스트 추가, 누적 9333 tests

한 줄 본질 정합

Pack 6 형사 도메인 anomaly closed-loop completion — 시그널 감지 → LLM 가설 → action library 보강 → 운영자 즉시 행동.

본 세션 2 capability 가 한 줄 본질의 closed-loop 마감:

  1. action layer 완성 — 시그널 → 가설 → 액션 4 source × 2 status 매트릭스 cover. anomalyHypotheses 카드가 표시만 하는 게 아니라 행동 가능
  2. naming 정합 — Pack 1~6 도메인 통합 후 5 sweep (5 + 6 + 7 + 8 + 9) 가 모두 같은 SSoT (CASE_DOMAIN_TYPES) 로 수렴

누적 (2026-05-15~18 전체)

  • 머지 PR 92 + 1 = 93건 (squash, 본 PR 1건 포함 예정)
  • 9333 누적 테스트 통과 (web 8493 + ops 845)
  • 한 줄 본질 핵심 기능 누적:
    • #17~#32 (선행 16 세션)
    • #33: anomaly action library + CaseDomainType canonical swap ← Pack 6 운영 anomaly 행동 layer + naming 정합

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출 — 사무소 별 historical 데이터 baseline 후 추가
  3. apps/web 잔여 RecoveryType import 사이트 점진 sweep — @deprecated JSDoc 가 가르쳐주는 위치 1-2 파일/세션 (e.g. types.ts, criminal-portfolio.ts, party-labels.ts)
  4. anomaly 가설 카드 UI 보강 — curated action 의 scenarioCardId 가 ops scenarios 페이지로 deep link
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #34 — CaseDomainType sweep 10 (10 파일 일괄) (1 capability)

자율 모드 — 후속 #33 의 다음 세션 후보 5건 중 자율 가능 1건 (#3 sweep 10) ship. 외부 환경 의존 4건 잔여.

머지 PR (1 commit, branch feat/case-domain-type-sweep-10)

commit분류핵심 변경
ADR 0028 sweep 10#1 RECOVERY_TYPE_LABEL → CASE_DOMAIN_TYPE_LABEL10 파일 일괄 perl 정규식 sweep (negative lookbehind (?<![A-Za-z])). 5 adapter (answer-brief · complaint · demand-notice · payment-order · preparatory-brief) + cases/_lib (case-recovery-type · case-summary-print · recovery-snapshot-schema) + legacy/_lib (chronicle-chapters · v2-query-expansion). recovery-snapshot-schema 가 RECOVERY_TYPES re-export 도 CASE_DOMAIN_TYPES 로 swap (consumer 0건 확인 후 안전 진행)

Ship 한 capability

  • deprecated alias 사용 사이트 10건 정리 — @deprecated JSDoc 도입 후 첫 점진 sweep. 잔여 약 ~10 파일 (UI 컴포넌트 + types.ts + dashboard 카드). 모든 변경 alias referentially 동일, 동작 무변화

기술 결정

결정이유
1 PR 1 패턴 (RECOVERY_TYPE_LABEL)RecoveryType 타입은 cases 컴포넌트 50+ 곳 호출, 한 PR 으로 묶으면 diff 폭주. label const 만 먼저 청소
perl 정규식 + negative lookbehindRecoveryTypeLabel 같은 흡사 토큰 보존. 이전 sweep 7 사고 (sed BSD 한계) 회피
recovery-snapshot-schema re-export rename 가능 확인 후 진행consumer 0 확인 — from "...recovery-snapshot-schema" import 중 RECOVERY_TYPES 가져가는 곳 없음. break risk 0

검증

  • apps/web type-check 통과
  • apps/web 709 test files / 8488 tests 통과 (parity 가드 + 모든 cases adapter 테스트 그대로 통과)

한 줄 본질 정합

Pack 1~6 19 종 도메인의 IDE 가르침 효과 production — 신규 코드 자연스럽게 CaseDomainType 사용.

본 세션 1 capability 가 코드베이스 일관성 보강:

  1. 점진 sweep 시동 — sweep 9 의 @deprecated 가 IDE 에서 가르치는 위치 중 10건 청소. 다음 세션이 잔여 ~10건 마저 정리하면 sweep 완료

누적 (2026-05-15~18 전체)

  • 머지 PR 93 + 1 = 94건 (squash, 본 PR 1건 포함 예정)
  • 8488 누적 테스트 통과 (web 8488, ops 845 변동 없음)

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출 — 사무소 별 historical 데이터 baseline 후 추가
  3. sweep 11 — UI 컴포넌트 (RecoveryTypeControls · RecoveryTab · RecoveryTypeChangeAlert · ClientInsightCard) + dashboard 카드 (DashboardRecoveryTypeCard) + wizard config (~10 파일 잔여)
  4. anomaly 가설 카드 UI 보강 — curated action 의 scenarioCardId 가 ops scenarios 페이지로 deep link
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

자율 모드 — 후속 #34 의 다음 세션 후보 5건 중 자율 가능 1건 (#4 anomaly card scenarioCardId deep link) ship. 외부 환경 의존 4건 잔여.

commit분류핵심 변경
Pack 6.23 anomaly deep link#1 추천 액션 → ops 시나리오 1 클릭 진입apps/ops/app/(ops)/dashboard/_lib/scenario-card-link.ts (NEW) — resolveScenarioCardPath(id) 순수 함수가 SCENARIO_CATEGORIES 순회로 cardId → /scenarios/[domain]/[card] 경로 변환. 미등록 → null. DynamicHypothesisCard 가 scenarioCardId resolves 시 Next.js Link 로 렌더 (blue underline). suggested-actions.ts 의 curated scenarioCardId 도 정정 — 실제 등록 카드 (record-rag-eval-run·record-refinement-feedback) 만 deep link, 운영 가이드형 (criminalStuck·docgenStats) 은 plain text

Ship 한 capability

  • 추천 액션 1 클릭 진입 — anomaly 가설 카드 추천 액션 중 ops 시나리오 카드 매핑된 액션은 클릭만으로 시나리오 페이지 진입. 운영자가 추천 받자마자 즉시 시나리오 실행으로 closed-loop
  • fallback safety — 미등록 scenarioCardId 면 plain text 로 fallback, broken link 0 보증 (정규식 sweep 시 cardId 가 외래 키처럼 동작)

기술 결정

결정이유
순수 함수 lookup (SCENARIO_CATEGORIES 순회)O(N) 이지만 N ≈ 90 카드로 작음. Map cache 도입 시 SCENARIO_CATEGORIES 변경 동기화 부담 — 매 호출 순회가 충분히 빠름. 18 테스트로 회귀 차단
dashboard _lib/ 에 위치 (공유 lib 아님)현재 단일 호출 사이트. 다른 페이지에서 쓰일 때 apps/ops/lib/ 로 promote 검토
curated 액션의 scenarioCardId 자정 (재정의 아닌 정정)처음 임의로 만든 ID 가 실제 SCENARIO_CATEGORIES 에 없었음. 직접 매핑 가능한 카드만 ID 보존 — operational guide 형 액션은 plain text (web URL 직접 표기)
Next.js Link 사용client-side navigation, prefetch 자동. <a href> 사용 시 풀 리로드 비용

검증

  • apps/ops type-check + 108 test files (851 tests) 통과 (+6 신규)
  • apps/web type-check + 709 test files (8488 tests) 통과 (suggested-actions 12 testes 갱신)

한 줄 본질 정합

anomaly closed-loop 의 마지막 step — 가설·시그널 → 액션 → 시나리오 진입 모두 한 카드에서.

본 세션 1 capability 가 운영자 안목 + 행동 사이의 마찰 제거:

  1. deep link — anomaly 가설 카드 자체가 시나리오 진입점. ops 콘솔 navigation 0

누적 (2026-05-15~18 전체)

  • 머지 PR 94 + 1 = 95건 (squash, 본 PR 1건 포함 예정)
  • 9339 누적 테스트 통과 (web 8488 + ops 851)

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출
  3. sweep 11 — UI 컴포넌트 (RecoveryTypeControls · RecoveryTab · RecoveryTypeChangeAlert · ClientInsightCard) + dashboard 카드 (DashboardRecoveryTypeCard) + wizard config (~10 파일 잔여)
  4. anomaly 가설 카드 추가 정합 — proposedActions 의 web URL (/cases?caseFlowStage=5) 도 진짜 Link 로 렌더 (현재는 label 텍스트 안에 string)
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #36 — CaseDomainType sweep 11 (12 파일) (1 capability)

자율 모드 — 후속 #35 의 다음 세션 후보 5건 중 자율 가능 1건 (#3 sweep 11) ship.

머지 PR (1 commit, branch feat/case-domain-type-sweep-11)

commit분류핵심 변경
ADR 0028 sweep 11#1 UI/dashboard/wizard alias rename12 파일 perl 정규식 sweep — _recovery 3 (RecoveryResultSummary · RecoverySnapshotHistory · RecoveryTypeChangeAlert) + RecoveryTab + cases/new 3 (CaseWizardSuccess · Step3DomainInfo · wizardConfig) + ClientInsightCard + DashboardRecoveryTypeCard + docgen-adapter + legacy ScannedUploadModal · case-type-normalize. wizardConfig 만 RecoveryType 타입 import → CaseDomainType (4 occurrence). 나머지 11 파일은 RECOVERY_TYPE_LABEL → CASE_DOMAIN_TYPE_LABEL

Ship 한 capability

  • production code alias cleanup 진척 — sweep 10 (10 파일) + sweep 11 (12 파일) = 22 파일 production alias 정리. 잔여 약 ~5 파일 (test 파일은 별도 sweep 예정)

기술 결정

결정이유
1 PR 12 파일sweep 10 (10 파일) 검증 후 1.2배 규모 진행. perl 정규식 + type-check + 전체 test 1회 통과로 회귀 0
test 파일 별도 sweep 보류테스트는 직접 영향 없음. 한 번에 모두 정리할 때까지 알리아스 동작 보존 — 같은 PR 에 묶으면 diff 폭주
다음 세션 candidate 에 anomaly Link 추가 정합 등록sweep 마감까지 1-2 PR 남음. anomaly 카드의 web URL 진짜 Link 화 가능성 candidate 보존

검증

  • apps/web type-check + 709 test files (8488 tests) 통과

한 줄 본질 정합

코드베이스 명명 일관성 — 다음 sweep 1-2 회 후 마감.

누적 (2026-05-15~18 전체)

  • 머지 PR 95 + 1 = 96건 (squash, 본 PR 1건 포함 예정)
  • 9339 누적 테스트 통과

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출
  3. sweep 12 — 잔여 test 파일 ~13 (non-debt-parity-* + business-logic-* + recovery-type-icon-map.test + RecoveryResultSummary.logic.test + party-labels.test) 일괄
  4. anomaly 가설 카드 web URL 진짜 Link 화 — /cases?caseFlowStage=5 텍스트 매칭 → Next.js Link
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #37 — CaseDomainType sweep 12 (test 파일 19) (1 capability)

자율 모드 — 후속 #36 의 다음 세션 후보 5건 중 자율 가능 1건 (#3 sweep 12) ship.

머지 PR (1 commit, branch feat/case-domain-type-sweep-12)

commit분류핵심 변경
ADR 0028 sweep 12#1 test 파일 alias rename19 test 파일 perl 정규식 sweep — non-debt-parity-A1~A14 (14) + business-logic-cases-firm/client-doc-checklist + RecoveryResultSummary.logic.test + recovery-type-icon-map.test + party-labels.test. 3 패턴 (RECOVERY_TYPES · RECOVERY_TYPE_LABEL · RECOVERY_TYPE_VALUES). 명시적 alias 계약 테스트 (recovery-input-schemas.test · recovery-type-constants.test) 는 sweep 제외 — 양쪽 alias 동작 검증 가드로 유지

Ship 한 capability

  • alias sweep 누적 41 파일 마감 (sweep 10 10 + sweep 11 12 + sweep 12 19). 잔여 alias 사용 사이트 = 2 (의도적 alias 계약 테스트)

기술 결정

결정이유
recovery-input-schemas.test / recovery-type-constants.test 보존두 테스트는 alias 동작 회귀 가드 — RecoveryTypeSchema.safeParse(...)·Object.keys(RECOVERY_TYPE_LABEL) 등 alias 가 실제로 working 임을 검증. 신규 코드는 안 쓰지만 alias 보존 contract 강제
19 파일 1 PRsweep 11 12 파일 후 검증 패턴 충분히 성숙. type-check + 8488 tests 1회 통과로 회귀 0
RecoveryType 타입 자체는 별도 sweepStep1RecoveryType.tsx (filename) · recoveryType (Firestore field name) 같은 식별자 충돌 위험. 이후 컴포넌트 rename 시 함께

검증

  • apps/web type-check 통과
  • apps/web 709 test files / 8488 tests 통과

한 줄 본질 정합

alias migration 마감 step — 41 파일 정리 후 잔여 = alias 가드 2 테스트만.

누적 (2026-05-15~18 전체)

  • 머지 PR 96 + 1 = 97건 (squash, 본 PR 1건 포함 예정)
  • 9339 누적 테스트 통과

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 9 단계 평균 처리 일수 ETA 산출
  3. component-level RecoveryType identifier rename — Step1RecoveryType.tsx, RecoveryTab.tsx, RecoveryTypeChangeAlert.tsx, RecoveryTypeControls.tsx, RecoveryTypeSelector.tsx 등 파일·컴포넌트 rename (Pack 6.X sub-numbered, 후속 작업)
  4. anomaly 가설 카드 web URL 진짜 Link 화 — 우선순위 낮음 (cross-app 복잡도 + 단일 occurrence)
  5. 외부 환경 의존 4건 (dev hydration · production Gemini · 시각 검수 · e2e)

2026-05-18 후속 #38 — Pack 6.21 형사 9 단계 평균 정체 일수 (1 capability)

자율 모드 — 후속 #37 의 다음 세션 후보 5건 중 자율 가능 1건 (#2 ETA) ship.

머지 PR (1 commit, branch feat/pack6-21-criminal-phase-eta)

commit분류핵심 변경
Pack 6.21 avgDaysByPhase#1 단계별 평균 정체 일수CriminalPortfolioStats.avgDaysByPhase: Partial<Record<CriminalPhase, number>> 추가. computeCriminalPortfolio 가 활성 사건 (finalized/enforced 제외) 의 daysAtCurrentPhase 를 단계 별로 모아 mean 계산. DashboardCriminalPortfolioCard 가 9 단계 분포 row 에 "평균 N일" inline 표시 (Math.round). 5 신규 단위 테스트

Ship 한 capability

  • 변호인 단계별 정체 가시화 — dashboard 의 9 단계 분포가 단순 건수에서 "단계 X 에서 평균 Y 일 정체" 까지 보여줌. stuckCount (90일+) 와 보완 관계 — stuckCount 는 극단 표본, avgDays 는 모든 활성 사건 평균
  • historical baseline 없이도 운영 가시화 가능 — 진정한 단계 간 전이 평균 일수 (ETA) 는 phase transition log 필요. 본 PR 은 활성 sampling proxy 로 동등한 운영 통찰 제공

기술 결정

결정이유
활성 sampling (현재 단계 머문 일수)phase transition log infrastructure 없이 즉시 운영 가능. 진정한 ETA 는 historical 데이터 누적 후 별도 sweep. 변호인 의사결정에 active sampling 충분 (어느 단계 처리 부담 큰지 즉시 보임)
Partial<Record<...>> (optional keys)sample 0 단계는 키 없음 → UI 가 자연스럽게 fallback ("평균 N일" 행 미표시)
Math.round 정수화운영 표시 "45일" vs "44.7일" 둘 다 같은 의사결정 결과. 정수가 가독성 우선
inline "· 평균 N일" 표시별도 라인 추가 시 카드 vertical density 폭증. count/% 와 한 줄에 — text-[10px] 작게

검증

  • apps/web type-check 통과
  • apps/web 709 test files / 8493 tests 통과 (+5 신규)

한 줄 본질 정합

형사 portfolio 단계별 처리 속도 시각화 완성 — 변호인이 dashboard 5초 헤드라인에서 "어디서 정체" 직관.

누적 (2026-05-15~18 전체)

  • 머지 PR 97 + 1 = 98건 (squash, 본 PR 1건 포함 예정)
  • 9344 누적 테스트 통과

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 단계 간 전이 평균 일수 (진정한 ETA) — phase transition activity log 누적 후
  3. component-level RecoveryType identifier rename (계속)
  4. anomaly 가설 카드 web URL 진짜 Link 화 (우선순위 낮음)
  5. 외부 환경 의존 4건

2026-05-18 후속 #39 — Pack 6.24 anomaly 카드 web URL cross-origin 앵커 (1 capability)

자율 모드 — 후속 #38 의 다음 세션 후보 5건 중 자율 가능 1건 (#4 anomaly Link) ship.

commit분류핵심 변경
Pack 6.24 anomaly URL anchor#1 label 안 path 자동 앵커apps/ops/lib/web-app-url.tsgetWebAppOrigin() (dev/test localhost:3000, prod NEXT_PUBLIC_WEB_APP_ORIGIN env 우선 + same-domain fallback) + toWebAppUrl(path) + WEB_APP_PATH_REGEX (9 root path 보수적). apps/ops/app/(ops)/dashboard/_lib/render-action-label.tsx — label text 에서 web 앱 path 발견 시 ReactNode 로 split + <a target="_blank"> 앵커. DynamicHypothesisCard 가 scenarioCardId 없으면 renderActionLabel 호출 (있으면 기존 Link). 9 신규 단위 테스트

Ship 한 capability

  • anomaly 카드 액션 1 클릭 진입 완전화 — scenarioCardId 등록 카드는 Next.js Link (Pack 6.23), label 안 web path 는 cross-origin 앵커 (Pack 6.24). 운영자가 가설 카드에서 모든 추천 액션을 1 클릭 진입
  • 9 root path 보수적 매칭/cases·/dashboard·/legacy·/portal·/docs·/clients·/finance·/revenue·/settings. 자유 텍스트 안의 우연한 /word 토큰은 매칭 안 함

기술 결정

결정이유
Next.js Link 대신 plain <a target="_blank">cross-origin (ops → web) navigation. Next.js Link 는 same-origin 가정 → 의도와 다른 ops origin 으로 잘못 라우팅
getWebAppOrigin() 3 단계 fallbackdev localhost:3000 (JourneyRunPanel 동일) → prod env → window.location.origin (same-domain 배포). server-side render 부재 → 빈 문자열 (의도 — env 설정 강제)
regex 안 \?[A-Za-z0-9_=&%.-]* query stringencoded char 일부 (% .) 허용. 한국어 query 미지원 — caller 가 ASCII encoded path 전달
9 root 화이트리스트 (탐색 회피)"/cases" 등 root path 만 매칭. 무차별 /[a-z]+ 패턴 사용 시 /cases?caseFlowStage=5 진행 중 의 "진행" 같은 단어가 path 시작으로 오인 가능

검증

  • apps/ops type-check + 109 test files (860 tests, +9 신규) 통과
  • 9353 누적 (web 8493 + ops 860)

한 줄 본질 정합

anomaly closed-loop UI 정합화 — 가설 + scenarioCardId Link + label web URL 앵커 3 layer.

누적 (2026-05-15~18 전체)

  • 머지 PR 98 + 1 = 99건 (squash, 본 PR 1건 포함 예정)
  • 9353 누적 테스트 통과

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. 단계 간 전이 평균 일수 (진정한 ETA) — phase transition activity log 누적 후
  3. component-level RecoveryType identifier rename (계속)
  4. NEXT_PUBLIC_WEB_APP_ORIGIN env 정합 (env.example 추가 · production 배포 절차)
  5. 외부 환경 의존 4건

2026-05-18 후속 #40 — env 정합 + sweep 13 (RecoveryType type identifier 3 파일) (2 capability)

자율 모드 — 후속 #39 의 다음 세션 후보 5건 중 자율 가능 2건 (#3 sweep + #4 env) 일괄 ship.

머지 PR (2 commit, branch feat/web-app-origin-env)

commit분류핵심 변경
docs(env) NEXT_PUBLIC_WEB_APP_ORIGIN#1 env example 정합apps/ops/.env.example 에 NEXT_PUBLIC_WEB_APP_ORIGIN 등록. dev/test 미설정 = localhost:3000, prod 미설정 = same-domain fallback. Pack 6.24 anomaly URL 앵커 + JourneyRunPanel cross-app 진입 패턴 표준화
ADR 0028 sweep 13#2 RecoveryType type identifier 3 파일step3-schema.ts + party-labels.ts + Step3DomainInfo.tsx 의 type RecoveryType import + 함수 시그너처 매개변수 RecoveryType 식별자 → CaseDomainType. negative lookbehind 로 PreviewRecoveryType 같은 다른 식별자 보존

Ship 한 capability

  • env 명세 완비 — Pack 6.24 의 cross-origin URL 앵커 옵션이 .env.example 에 명시. production 다른 도메인 배포 시 1 줄 설정으로 활성화
  • type identifier sweep 누적 44 파일 (sweep 10+11+12+13 production 25 + test 19). 잔여 = 컴포넌트 file rename (Step1RecoveryType.tsx) + local 식별자 + 별도 의미의 corpus enum (case-classification-corpus)

기술 결정

결정이유
env example 만 — 코드 추가 변경 0Pack 6.24 의 getWebAppOrigin() 이 이미 env 분기 처리. 본 PR 은 명세 정합 (개발자 onboarding)
컴포넌트 file rename (Step1RecoveryType.tsx) 보류8+ 파일 string 참조 (test grep 패턴, e2e specs 등) 수정 필요. 미충분한 가치 (aesthetic) 대비 break risk 큼. local 식별자 Step1RecoveryType (AiPrefillCard 등) 도 internal naming 으로 유지
case-classification-corpus 의 RecoveryType 별도 enum 유지AI 분류 corpus 의 local 도메인 enum — 시맨틱 분리. canonical CaseDomainType 와 별개 결합도 0

검증

  • apps/web type-check 통과
  • apps/web 709 test files / 8493 tests 통과

한 줄 본질 정합

운영 가이드 + 명명 일관성 — production deployment 정합 + 식별자 sweep 누적 44 파일.

누적 (2026-05-15~18 전체)

  • 머지 PR 99 + 1 = 100건 (squash, 본 PR 1건 포함 예정) 🎉
  • 9353 누적 테스트 통과

다음 세션 후보

  1. CriminalDefaultsSection e2e (외부 환경)
  2. phase transition activity log (진정한 ETA baseline) — Pack 6.21 후속
  3. Step1RecoveryType.tsx 파일 rename → Step1CaseDomainType.tsx (8+ 파일 단일 PR — 별도 세션)
  4. AnomalyHypothesis schema 확장 — proposedActions 의 href field (label 의존 회피, 명시 URL/scenarioCardId 분리)
  5. 외부 환경 의존 4건