# PR-RAG-Time-1 — 1주 운영 관찰 Baseline (Snapshot)

**측정일**: 2026-05-03 (배포 직후, main `5185501`)
**대상 endpoint**: `GET /api/search/?q=...&debug=true&limit=5`
**비교 시점**: 2026-05-10 경 1주 후 동일 6 쿼리 재측정 → ranking / freshness_ms / total_ms 회귀 점검
**원본 JSON**: `reports/freshness_decay_observation_baseline.json` (1주 후 자동 비교 가능)

## 4 관찰 포인트

1. **news/law_monitor 가 과도하게 boost 되지 않는지** — multiplier floor 0.7 안에서 동작하므로 base score 가 약하면 freshness 만으로 상위 못 올라가야 함.
2. **오래된 핵심 문서가 부당하게 밀리지 않는지** — 산안법/KGS Code 원문(law_monitor) 이 floor 0.7 보장에 의해 사라지지 않아야 함.
3. **drive_sync / manual / Study / ai_drafted 비적용 가드 유지** — policy=None 으로 base 그대로.
4. **freshness_ms 와 total latency 회귀 없음** — 현 baseline freshness_ms 0.4~3.1ms / total 200~350ms.

회귀 신호 (1주 후 실측):
- top 3 ranking 의 doc_id 변동이 6 쿼리 중 3 이상 발생
- freshness_ms p95 > 10ms (현재 max 3.06ms 대비 3× 초과)
- total_ms p95 > 500ms
- 사용자 명시 피드백 ("검색 결과가 이상하다")
- `policy != None` 인 row 가 비정상적으로 적게/많게 나오는 분포 변화

## 6 쿼리 baseline 요약

### 쿼리별 정책 적용 분포
| 쿼리 | n | law_365d | news_90d | None | freshness_ms | total_ms |
|---|---:|---:|---:|---:|---:|---:|
| 중대재해 사고 | 5 | 3 | 0 | 2 | 0.486 | 250 |
| 최근 중대재해 | 5 | 1 | 2 | 2 | 0.487 | 287 |
| 산안법 개정 | 5 | 1 | 0 | 4 | 3.055 | 200 |
| KGS Code 개정 | 5 | 0 | 0 | 5 | 0.434 | 272 |
| 위험성평가 최근 동향 | 5 | 0 | 0 | 5 | 0.430 | 284 |
| 가스 사고 최근 사례 | 5 | 0 | 2 | 3 | 0.444 | 350 |
| **합계 30** | | **5** | **4** | **21** | avg 0.89 | avg 274 |

### 쿼리별 top-5 doc_id (1주 후 비교 기준)
```
중대재해 사고:        3854 → 10571 → 10573 → 3922 → 3877
최근 중대재해:       10571 → 11566 → 3922 → 6695 → 11825
산안법 개정:         10572 → 4026 → 10573 → 5229 → 10569
KGS Code 개정:       11647 → 13914 → 11692 → 11693 → 11691
위험성평가 최근 동향:   5243 → 5229 → 10574 → 11685 → 11568
가스 사고 최근 사례:   11684 → 11564 → 11565 → 7107 → 6707
```

## 발현된 정책 sample (검산)

| query | doc_id | source | age (일) | base | adj | ratio | policy |
|---|---:|---|---:|---:|---:|---:|---|
| 중대재해 사고 | 3854 | law_monitor | 29 | 0.7133 | 0.7016 | 0.9835 | law_365d |
| 중대재해 사고 | 10571 | drive_sync | 8 | 0.6859 | 0.6859 | 1.0000 | None |
| 중대재해 사고 | 3922 | law_monitor | 29 | 0.6872 | 0.6759 | 0.9835 | law_365d |
| 최근 중대재해 | 6695 | news | 18 | (계산) | (계산) | (계산) | news_90d |
| 가스 사고 최근 사례 | 7107 | news | 17 | (계산) | (계산) | (계산) | news_90d |

검산: age=29, half_life=365 → decay = exp(-ln(2) × 29/365) = **0.9451**.
multiplier = 0.7 + 0.3 × 0.9451 = **0.9835** (실측 ratio 와 일치). ✓

## 관찰 신호 (현재 시점 메모)

**중립**:
- news/law_monitor 가 30 rows 중 9건 (30%) 발현 — 6 쿼리가 시사 도메인 키워드 위주이므로 적정.
- floor 0.7 가드 안에 있어 base score 가 약한 row 는 절대 상위 침투 못 함 (관찰 포인트 1 통과 조건).

**잠재 회귀 후보**:
- "최근 중대재해" 쿼리에서 top 2 가 manual/drive_sync 8일 → 5일 짜리 학습 자료. news/law (18일) 는 4-5위. 사용자가 "최근" 키워드로 뉴스를 기대했는데 manual 이 우선이라면 1주 후 사용 패턴에 따라 base score(reranker) 재조정 필요. 단 이건 freshness 문제 아닌 reranker semantic match 의 문제.
- "가스 사고 최근 사례" 도 동일 패턴 — manual(BLEVE/UVCE 학습) 이 news(폭발 사고 기사) 보다 위.

## 1주 후 비교 절차

```bash
# GPU 서버에서 1주 후 재실행
TOKEN=$(...)
python3 /tmp/observe_freshness.py "$TOKEN" > /tmp/obs_week1.json

# 로컬에서 baseline vs week1 diff
python3 -c "
import json
b = json.load(open('reports/freshness_decay_observation_baseline.json'))
w = json.load(open('/tmp/obs_week1.json'))
for qb, qw in zip(b, w):
    bids = [r['id'] for r in qb['results'][:3]]
    wids = [r['id'] for r in qw['results'][:3]]
    if bids != wids:
        print(f'{qb[\"query\"]}: top3 변동 {bids} → {wids}')
    fb, fw = qb['timing_ms']['freshness_ms'], qw['timing_ms']['freshness_ms']
    if fw > 3 * fb:
        print(f'{qb[\"query\"]}: freshness_ms 회귀 {fb}ms → {fw}ms')
"
```

회귀 발견 시 → rollback 검토 (search_pipeline.py:303~307 hook 비활성 또는 freshness_decay.py 의 `apply_freshness_decay` early-return).

## 관련 파일
- 구현: `app/services/search/freshness_decay.py`
- hook: `app/services/search/search_pipeline.py:303-307`
- schema: `app/api/search.py` `SearchResult.freshness_debug`
- tests: `tests/test_freshness_decay.py` (31 passed)
- plan: `~/.claude/plans/pr-rag-time-1-freshness-decay.md`
- 배포 commit: `5185501`

## 1주 후 결과 (2026-05-12)

PASS. top3 변동 0/6, freshness_ms max 0.54ms, total_ms max 413ms, policy 분포 동일 (9/30). 상세: `reports/freshness_decay_observation_week1.md`.
