# Document Parser 상세 설계

## 1. 설계 원칙

1. 문서는 **규칙 기반 추출 → LLM 보강 → 병합** 순서로 처리한다.
2. 추출 결과는 **event taxonomy**와 모순되면 review 대상이다.
3. LLM은 숫자를 계산하거나 invent하지 않는다.
4. 모든 핵심 필드는 evidence span을 남긴다.

## 2. 파서 입력

입력 필수 항목:
- filing_id
- accession_no
- cik
- issuer_name
- symbol
- form_type
- filing_ts
- document_id
- document_type
- normalized_text
- text_hash
- optional_xbrl_summary
- optional_prior_guidance_snapshot

## 3. 단계별 파서 흐름

### Step A. Pre-classification
문서 종류 추정:
- earnings release
- shareholder letter
- contract announcement
- regulatory/approval update
- guidance update
- misc material event

실패 시:
- `event_type = unknown`
- review queue로 보낼 수 있음

### Step B. Rule extraction
규칙 기반으로 먼저 뽑을 필드:
- item numbers
- guidance phrases (`raising`, `updating`, `expects`, `reaffirms`, `withdraws`)
- one-off markers (`tax benefit`, `gain on`, `fair value`, `impairment`, `restructuring`, `non-GAAP`)
- demand markers (`backlog`, `bookings`, `pipeline`, `orders`, `customers`)
- pricing markers (`pricing`, `price increase`, `higher ASP`, `price realization`)
- margin markers (`gross margin`, `operating margin`, `expanding margin`)
- direct numeric snippets for revenue/EPS/guidance if present

### Step C. LLM enrichment
LLM이 판단할 필드:
- `event_direction`: bullish / bearish / mixed / neutral / unknown
- `guidance_direction`: raised / inline / lowered / withdrawn / ambiguous / unknown
- `quality_assessment`: high_quality / mixed_quality / low_quality / unknown
- `demand_strength`: strong / moderate / weak / unclear
- `pricing_power`: strong / present / absent / unclear
- `management_tone`: strong_positive / mild_positive / neutral / mild_negative / strong_negative / mixed
- `oneoff_suspicion`: none / possible / likely
- `customer_expansion`: yes / no / unclear
- `structural_change_flag`: yes / no / unclear

### Step D. Canonical merge
병합 규칙 예시:
- 숫자: rule parser 우선
- taxonomy/classification: rule strong hit가 있으면 rule 우선, 그 외는 llm
- quality/tone: llm 우선
- one-off: rule hit와 llm 판단을 모두 보존, canonical은 더 보수적인 값 사용

## 4. 필수 출력 필드

최소 필수 출력:
- `event_instance_id`
- `source_filing_id`
- `symbol`
- `event_type`
- `event_direction`
- `guidance_direction`
- `quality_assessment`
- `oneoff_suspicion`
- `confidence_overall`
- `evidence_refs`
- `parser_version`
- `prompt_version`
- `schema_version`

## 5. evidence span 정책

각 핵심 필드는 evidence span 1개 이상 권장:
- line offsets 또는 character offsets
- 최대 3개 span
- 증거 없는 강한 주장 금지

예시:
```json
{
  "guidance_direction": "raised",
  "guidance_direction_confidence": 0.88,
  "guidance_direction_evidence": [
    {"start": 1245, "end": 1320, "text": "raising full-year revenue guidance..."}
  ]
}
```

## 6. 금지사항

- 문서에 없는 실적 추정치/컨센서스 생성
- 문서에 없는 티커/세그먼트 생성
- confidence가 낮은데도 단정적 레이블 출력
- JSON schema를 어기는 자유형식 텍스트 반환
- one-off suspicion이 높은데 high_quality로 단정

## 7. fallback 정책

### 규칙 파서 실패
- null 허용
- 실패 사유를 `parse_warnings`에 남김
- LLM 보강을 시도하되 hallucination 금지

### LLM 실패
- rule-only canonical record 생성
- `llm_status = failed`
- review queue 생성

### JSON validation 실패
- 1회 자동 수정 요청 가능
- 그래도 실패면 `parse_failed` 상태로 저장

## 8. 수동 검수 트리거

다음은 반드시 검수 후보:
- `guidance_direction = ambiguous|unknown`
- `quality_assessment = unknown`
- `oneoff_suspicion = likely`
- `confidence_overall < 0.70`
- rule과 llm의 `event_direction` 충돌

## 9. 개발 시 구현 단위

추천 구현 순서:
1. text normalizer
2. rule-based keyword extractor
3. line/span mapper
4. llm client wrapper
5. schema validator
6. canonical merge function
7. review queue writer

각 단계는 독립적으로 테스트 가능해야 합니다.
