본문으로 건너뛰기

Pack 1 Core Layer

최근 갱신: 2026-04-22 (오버나이트 자율 세션 25 PR 반영)

Pack 1 민사 회수 6 유형의 엔진 · 출력 템플릿 · 법원 서면 · 어댑터 를 모두 순수 함수로 구현한 3-tier 아키텍처.

  • Tier 1 — 엔진 (순수 함수 계산): 6 유형 × _lib/*-settlement.ts
  • Tier 2 — 출력 템플릿 (결정론 텍스트 생성):
    • 공통 3부작 (_lib/recovery-output/ — 청구취지 · 요약 계산표 · CSV)
    • 법원 서면 5종 (_lib/*-text.ts — 내용증명·지급명령·소장·답변서·준비서면)
  • Tier 3 — 어댑터 (CaseData + 엔진 결과 → 서면 입력): 3종 (지급명령·소장·답변서)

모든 Tier 는 AI 호출 0 · Firestore 호출 0 · 결정론. UI 와 Server Action 의 책임은 "이 3-tier 를 호출하고 결과를 렌더/저장" 까지.


1. Tier 1 — 회수 유형 엔진

#회수 유형엔진 파일핵심 규칙
1대여금debt-settlement.ts대여일부터 이자 연속 누적 · 민법 §477·§479
2공사대금construction-settlement.ts변제기 이후 지연손해금 · 상법 §54 default 6%
3구상금subrogation-settlement.ts대위변제일 즉시 이행기 · 법정이자 (민법 §441)
4약정금agreement-damages.ts이행기 이후 지연손해금 · 3분기 이율
5임대차보증금lease-deposit.ts공제 개념 + 반환 이행기 기산
6양수금assigned-claim.ts양도 메타 + 양도인/양수인 변제 분류

1.1 공통 규약

  • 입력: claim + repayments[] + asOfDate (YYYY-MM-DD, KST)
  • 출력: outstandingPrincipal · outstandingInterest/Damages · totalOutstanding · applications[] · engineVersion
  • 정수 원 단위 Math.floor 절사 — 원미만 금지
  • 365일 고정, 초일불산입·말일산입 (민법 §157)
  • 결정론: 같은 입력 → 같은 출력. 같은 날짜 변제는 id 사전순 tiebreak
  • engineVersion v1 stamp: 공식 변경 시 bump → snapshot drift 방어
  • Property test (fast-check, 100 runs/엔진) — 잔여 ≥ 0 · 원본 ≤ amount

1.2 이율 해결 (construction 이후 공통)

1순위: agreedRatePercent (민법 §397 ①) → rateSource = "agreed"
2순위: statutoryRatePercent === 6 → "statutory-commercial-6" (상법 §54)
3순위: 기본 → "statutory-civil-5" (민법 §379)

1.3 충당 순서 (§479)

지연손해금/이자 → 원본

지정충당 (§476) appropriationOverride:

  • "principal" — 원본 먼저, 잔액은 이자
  • "interest"/"damages" — 이자만, 초과분 drop

2. Tier 2 — 출력 템플릿

2.1 공통 3부작 (recovery-output/)

템플릿파일용도
청구취지 문장claim-text.ts소장·준비서면 붙여넣기
요약 계산표 (마크다운)summary-table.ts법원 제출용 한글 서식
CSV export (UTF-8 BOM)csv-export.ts엑셀 첨부 서면

각 템플릿은 범용 builder + 유형별 adapter 5종. 대여금은 기존 settlement-output/ 유지 (Phase 0 MVP).

2.2 법원 서면 5종

서면파일단계
내용증명demand-notice-text.ts소 전 (민법 §174 최고)
지급명령payment-order-text.ts독촉절차 (민소법 §462)
소장complaint-text.ts통상 · 소액재판 (소액 isSmallClaim 자동)
답변서answer-brief-text.ts피고 대응 (민소법 §256)
준비서면preparatory-brief-text.ts본안 진행 (민소법 §274)

모든 서면은:

  • 당사자·법원·제목·본문·첨부·서명 표준 섹션
  • 클립보드 복사 → 한글 서식 붙여넣기 전제 (HTML/PDF 는 별도 경로)
  • 중립 어조 — 협박·감정 표현 금지 (증거 가치 유지)

3. Tier 3 — 어댑터

어댑터파일매핑
지급명령payment-order-adapter.tsCaseData + calc → PaymentOrderInput
소장complaint-adapter.tsCaseData + calc → ComplaintInput (+ isSmallClaim 자동)
답변서answer-brief-adapter.tsCaseData → AnswerBriefInput (엔진 결과 불필요)

어댑터 책임:

  • 유형별 이자 기산일 자동 (이행기+1 또는 출재일)
  • 유형별 이자 명칭 자동 ("지연손해금"·"법정이자"·"이자")
  • 유형별 사건명/청구종류 자동 (RECOVERY_TYPE_LABEL)
  • CaseData.client/opponentParty 필드 매핑 헬퍼 동반

4. Unified Dispatch

4.1 recovery-dispatch.ts

const calc = calculateRecovery({ type: "construction", input: {...} });
// calc.type === "construction", calc.result === ConstructionSettlementResult (discriminated)

const text = buildRecoveryClaimText(calc, { plaintiffName, defendantName });
// 유형별 적절한 라벨·기산일·이자 명칭 자동

const summary = toRecoverySummary(calc);
// { type, outstandingPrincipal, outstandingInterest, totalOutstanding,
// appliedRatePercent, asOfDate, engineVersion }

4.2 document-bundle.ts

const bundle = buildDocumentBundle({ caseData, calc, court, filingDate, causeLines });
// {
// claimText, summaryText, csvText,
// paymentOrderText, complaintText,
// summary
// }

한 번의 호출로 사건의 전체 문서 풀세트 생성. UI "문서 풀세트" 버튼 직통.


5. Input Validation

5.1 recovery-input-schemas.ts

5 유형별 Zod 스키마 3조:

  • ClaimInputSchema · RepaymentInputSchema · SettlementInputSchema (top-level refine)

UI 폼 (React Hook Form + Zod resolver) · Server Action 경계 런타임 검증. 엔진 내부 validateInput 은 최종 방어선.

5.2 CaseData 확장

CaseData.recoveryType?: RecoveryType (optional) — 미지정 시 resolveCaseRecoveryType()"debt" 기본값.

6. Persistence & Diff

6.1 recovery-snapshot-schema.ts

6 회수 유형 공통 Firestore 스냅샷 Zod 스키마 (discriminated union).

  • 경로: tenants/{tid}/cases/{caseId}/recoverySnapshots/{id}
  • type 필드로 유형 분기. Interest (debt·subrogation) vs Damages (나머지 4) 필드 자동 구분.
  • frozen: literal(true) — 동결 스냅샷만 저장.
  • assertCurrentRecoveryEngineVersion(type, result) — 저장 직전 drift 방어.
  • RecoverySnapshotStaleError — 수정 시도 차단 에러.

6.2 recovery-summary-diff.ts

RecoveryResultSummary 비교 → 재계산/스냅샷 diff.

  • recoverySummaryDiff(from, to){ *Delta, asOfDateDeltaDays, engineVersionMismatch }
  • summarizeDiff(diff) → UI 한 줄 요약 "+1,234,567원 · 기준일 +31일"
  • 유형 불일치 시 RecoveryTypeMismatchError throw.

7. Phase 0 Week 4 Citation Precision Gate

7.1 측정 모듈 (lib/eval/citation-precision.ts)

  • computePrecision · computeRecall · computeF1 기본 메트릭
  • evaluateCitationPrecision(cases) — micro/macro 병행 집계
  • evaluateWeek4Gate(metrics) — Precision ≥ 0.95 hard gate
  • renderCitationPrecisionReport(metrics, gate) — 마크다운 리포트

7.2 Fixture (lib/eval/citation-fixtures.ts)

10 건 초기 ground-truth 데이터셋. 6 회수 유형 + multi-statute · 법원 계층 · no-citation · mixed 커버.

7.3 CLI Runner (scripts/eval-citation-precision.ts)

NODE_PATH=apps/web/node_modules npx tsx scripts/eval-citation-precision.ts
  • Fixture 전체 실행 → Precision/Recall/F1 계산 → 마크다운 리포트 표준출력 + reports/citation-precision-report.md 저장.
  • FAIL 시 exit 1 (CI 게이트 용).

8. 테스트 집계 (2026-04-22 세션 기준)

레이어신규 테스트
엔진 5 (공사대금·구상금·약정금·임대차·양수금)77
출력 템플릿 3 (청구취지·요약·CSV)32
법원 서면 529
어댑터 525
통합 (dispatch·bundle·E2E·CaseData type)34
Zod 스키마 (입력 · 스냅샷)27
Diff (Recovery summary)13
Week 4 Citation Precision (module · fixtures · CLI)20
합계~257

누적 프로젝트 테스트: 2112+.


7. UI 통합 대기 목록

Pack 1 Core Layer 는 완성. 아래는 UI 층 책임:

  1. Settlement 탭 분기: CaseData.recoveryType 으로 유형별 입력 폼 렌더.
  2. 문서 생성 버튼: buildDocumentBundle() 호출 → 결과 modal/drawer 표시.
  3. Server Action 래핑: Firestore snapshot 저장 + 버전 관리.
  4. 한글 서식 export: 텍스트 → 한글/PDF 변환 (Phase 1 후반).

8. 관련 문서