# task-3019 — 트렌드 헬스체크 경고 신뢰성 회복 (조사 → 원인 단정 → 수정)

**레벨**: Lv.2 · **팀**: dev7-team (이참나) · **회장 승인 완료** (2026-08-25)

## ★ 이 태스크의 목표는 "카운터 숫자 수정"이 아니다
**헬스체크 경고를 믿을 수 있게 만드는 것**이 목표다.

2026-08-25 경보 배선이 복구됐다(t3008). **내일 06:00 부터 이 경고가 회장 채팅방에 도달한다.**
경고가 오탐이면 **복구한 경보 체계의 신뢰가 첫날부터 깨진다.**

---

## 실측 (확정된 것과 미규명인 것을 구분하라)

### 확정된 것
```
daily_trend_collect.py:408
  sb.table("keyword_trends").upsert(...).execute()
  total_upserted += len(upsert_rows)     # ← 보낸 행 수를 센다. 실제 쓰인 행 수가 아니다
```

```
수집 자체는 정상이다:
  public.keyword_trends  84,354행 · 최근 유입 2026-08-24 21:00
  (ANU 가 프로덕션 DB 직독으로 확인)
```

```
★ ANU 오진 정정 — 이 표를 전제로 삼아라
  public.trend_data (1,626행 · 2026-04-30 정지)는 레거시 Google Trends 테이블이다.
  server/trend_collector.py 가 쓰는데 호출자 0건 = 휴면 경로. 고장이 아니다.
  ANU 가 이걸 "트렌드 4개월 정지"로 오진했다. 실제 라이브는 keyword_trends 다.
```

### ★ 미규명 — 이것을 먼저 밝혀라
```
헬스체크 실측 (2026-08-25 06:00 파이프라인 로그):
  ⚠️ 트렌드 수집: 0/2,000건 (기준 1,800)
  ⚠️ 포화도 수집: 1,000/2,000건 (기준 1,800)
  ⚠️ 랭킹 산출: 0건 (기준 1+)

수집이 되는데(어제 21:00 유입) 왜 헬스체크는 0 이라 하는가?
  · 헬스체크가 다른 테이블/다른 기간/다른 필터를 보는가?
  · 아니면 실제로 "최근 실행분"만 0 인가?
  · Step 3(daily_ranking_calc)는 "keyword_trends 최근 7일(period_end >= …) 데이터 없음"으로
    정상 중단했다. 이 period_end 기준과 유입 시각의 관계는?
```

---

## ★★ 조사와 수정을 분리하라 — 순서 엄수

### ① 집계 기준 대조 (수정 금지 단계)
**최근 실행 1회를 기준으로** 아래 3가지를 **표로** 대조하라:

| | 무엇을 | 값 |
|---|---|---|
| ① | `upsert` 에 보낸 행 수 (`len(upsert_rows)`) | ? |
| ② | 실제 DB 반영량 (해당 실행분이 `keyword_trends` 에 남긴 행) | ? |
| ③ | 헬스체크가 본 수치 — **대상 테이블 · 기간 · 필터 · 산식** | ? |

### ② 불일치 원인 단정
①의 표에서 어디가 어긋나는지 **하나로 특정**하라. 추정을 결론으로 쓰지 마라.

### ③ 원인에 대응하는 수정
②에서 특정된 원인만 고친다.
- `total_upserted` 가 원인이면 **실제 반영량을 세도록** 고친다
- 헬스체크 기준이 원인이면 **기준을 맞춘다**
- 둘 다면 둘 다

★ **①②를 건너뛰고 카운터만 고치는 것은 완료로 인정하지 않는다.** 증상 봉합이 된다.

---

## 범위 · 금지
**수정 허용**: `server/scripts/daily_trend_collect.py` · `server/scripts/daily_health_check.py`(기준 산식만) ·
관련 테스트

**금지**:
- `server/scripts/alert_notify.py` — t3008 결과물. 발송 경로는 건드리지 마라
- `server/trend_collector.py` / `trend_data` — **휴면 경로다. 고치지 마라.**
  (조사 중 별개 결함을 발견하면 **보고만**)
- `daily_ranking_calc.py` — Step 3 실패는 **결과**다. 선행이 정상화되면 자연히 풀린다
- `server/policy_analyzer.py` · `server/silson/**` · `server/main.py` · `src/**`
- **DB 데이터 대량 삭제·변경** (조사는 읽기로. 필요하면 트랜잭션 후 ROLLBACK)
- 자격증명 값을 저장소에 커밋

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "server/scripts/daily_trend_collect.py"
    - "server/scripts/daily_health_check.py"
    - "server/tests/**"
    - "memory/reports/task-3019.md"
  forbidden_paths:
    - "server/scripts/alert_notify.py"
    - "server/scripts/daily_ranking_calc.py"
    - "server/trend_collector.py"
    - "server/policy_analyzer.py"
    - "server/silson/**"
    - "server/main.py"
    - "src/**"
    - "extension/**"
  commands:
    - "python3"
    - "pytest"
    - "bash"
  merge_policy: "tiered"
  ttl_hours: 24
```

## 검증
1. **①의 대조표 제시** (3가지 수치 + 헬스체크 대상/기간/필터/산식)
2. **원인 단정 근거** — 왜 그것이 원인인지. 추정과 확정을 구분해 적어라
3. **수정 후 재실행** — 같은 실행분에서 헬스체크 결과와 DB 실측의 불일치가
   **해소되거나, 원인 있는 차이로 명확히 설명**되는지
4. **오탐 없음** — 정상적으로 적은 날(주말·계절성)에 실패로 잡히지 않는지.
   `season_calendar_check.py` 가 이미 있으니 그 맥락을 확인하라
5. **봉인** — 카운트가 다시 "보낸 행 수"로 되돌아가면 FAIL 하는 테스트. **변이로 실증**
6. `pytest` 회귀 유지 (**base 재측정 기준선**)

## ★ 세션 조기 종료 대책 (오늘 4건 발생 — 반드시 지켜라)
- **시작 즉시 작업 브랜치 + 드래프트 PR 을 먼저 열어라.** 마지막 긴 응답에 보고를 몰지 마라
- **단계마다** 진행 기록을 보고서 또는 PR 본문에 갱신하라 (특히 ① 대조표는 나오는 즉시 기록)
- 최종 보고는 **분할 출력**
- ★ **ANU 명세 전제가 틀렸다고 판단되면, 그 전제를 따른 구현을 진행하지 말고
  반증 결과를 먼저 기록한 뒤 ANU 에 보고하라.** (오늘 ANU 명세 오류 3건이 전부 봇에게 반증됐다.
  위 `trend_data` 정정도 그중 하나다)

## 운영 계약
- `origin/main`(=`934168e`) 기준 `git pull --ff-only` 후 시작
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.
- ★ cron 은 **디스크 파일**을 직접 실행한다. `/home/jay/projects/InsuRo` 가 최신인지 확인하라

## 완료 조건 (DoD)
**최근 실행 1회 기준으로 헬스체크 수치의 대상·기간·산식이 문서화되어 실제 DB 반영량과 대조 가능하고,
수정 후 같은 실행분에서 헬스체크 결과와 DB 실측의 불일치가 해소되거나 원인 있는 차이로 명확히 설명된다.**

## 보고
**PR 생성까지가 범위다. 머지는 ANU 가 한다. 자동 머지 금지.**
`memory/reports/task-3019.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"불일치 원인 규명 여부"** 를 담아라.