# [Lv.4] Integration Phase1 PR-A — 계약 V2 스키마 확장 (matrix 저장 + region)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/schemas/consultation_history_v1.py"
    - "server/routes/consultation_history_v1.py"
    - "server/migrations/**"
    - "supabase/migrations/**"
    - "docs/contracts/**"
    - "server/tests/**"
  forbidden_paths:
    - "extension/**"
    - "src/**"
    - ".github/**"
    - "server/main.py"
    - "server/customer_match.py"
    - "server/utils/legacy_write_guard.py"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "git"
  merge_policy: "tiered"
  ttl_hours: 24
```

## 배경·단일소스
- 설계 단일소스: `/home/jay/workspace/memory/plans/insuro-composite-design/integration-design-260721.md` (§7-c 정보량 갭 결정 반드시 읽어라).
- 리포: `/home/jay/projects/InsuRo`, base = 현 origin/main.
- 이건 **Integration Phase 1 의 PR-A(스키마 기반)** 이다. PR-B(접근제어)·PR-C(CRM검색)는 별도. **이 task 는 스키마/계약/마이그레이션/테스트만.**

## 왜 (실측 확정된 갭)
`consultation_history_v1` 은 보험사별 **합계**(`per_insurer.computed_sum` 등)만 저장하고, 웹 재분석 엔진 `server/composite_calculator.py::calculate_composite_from_matrix` 가 요구하는 **담보×보험사 격자**(`matrix = {insurers:[{name,code}], coverages:[{cd,name,amount,premiums:{보험사코드→보험료}}]}`)가 없다. → V1 만으론 웹 1·2·3사 재분석 불가. 회장 결정(가): **matrix 를 같은 audited 레코드 안에 저장**해 웹 완전 재분석 가능케 한다.

## 작업 (스키마 V2 확장 — 순수 additive)
1. **matrix 필드 추가** (`consultation_history_v1` envelope):
   - `ConsultationHistoryV1Request` 에 신규 필드 (예: `analysis_matrix`) 추가 — `composite_calculator` 가 그대로 먹는 구조(`{insurers, coverages[].premiums}`) 를 담는 JSONB.
   - `extra="forbid"` 유지. 신규 필드는 **선언된 필드**로 추가(미지 필드 아님).
   - **버전 처리**: 계약 V1 frozen 원칙상, 이 확장은 **계약 V2** 로 명시하거나 **V1 additive(하위호환 optional)** 중 택1 — **근거를 보고서에 명시**. 파일럿은 항상 matrix 를 보내므로 저장 가능해야 함. body_sha256/멱등 = 이 필드 포함해 1회 조립(같은 레코드).
2. **DB 컬럼 추가**: `consultation_history_v1` 테이블에 matrix JSONB 컬럼. **SQL 2파일 미러링**(`server/migrations/013_*.sql` + `supabase/migrations/20260719120000_*.sql`) 동일 반영.
3. **OK-only 뷰 갱신**: `consultation_history_v1_ok_only`(명시 컬럼 리스트)에 신규 컬럼 추가.
4. **customers.region 추가**: `region TEXT`(자유텍스트, nullable). SQL 미러링.
5. **계약 문서 갱신**: `docs/contracts/` 에 matrix 필드·region 반영. V2/additive 결정 명시.

## 제약
- **순수 additive.** 기존 필드/제약/멱등 unique scope `(fa_account_id, operation_scope, idempotency_key)` 변경 금지. per_insurer 등 기존 필드 유지.
- matrix 저장은 **그 FA 본인 고객·동의 하** 데이터라 허용(§2-2 대량payload 예외는 회장 결정). 단 **JWT 원문·consultantid·API 원본응답 은 여전히 저장 0**.
- extension/src/main.py/customer_match/legacy_guard **손대지 마라**(PR-B/C·미변경).
- 계약 문서(artifact)+스키마/SQL(runtime) 이 한 PR 에 같이 가는 건 **계약 V2 라는 단일 응집 변경**이라 의도적임(무관한 혼합 아님). 보고서에 명시.

## 검증 (전부 통과)
- 신규 테스트: matrix 필드 저장·조회 round-trip / matrix 로 `calculate_composite_from_matrix` 재분석이 **원 분석과 동일 결과** / region 저장 / 기존 멱등·per-FA·금지필드·FEATURE_DISABLED 회귀 0.
- `pytest server/tests -q -p no:randomly` → 기존 763 passed **감소 0** + 신규.
- SQL 2파일 diff 로 미러 동일성 증명.

## 완료
- `server/**`+`docs/contracts/**` 외 변경 0 (`git diff --stat`)
- worktree finish → PR → Gemini High 0 → ANU 독립검증. **머지 금지**(ANU/회장 판정).
- **ANU callback**(UTF-8 ≤3900 bytes, envelope: task_id·result_path·report_path·PR#·sha·one-line).
- ⚠️ 자기 완료가 scope-guard 로 막히면 `.done` 수동생성·scope 변조 금지 → result.json + ANU callback escalate. `FINISH_TASK_WORKTREE_STRICT=1` + 정확 base + worktree cwd 로 finish.
