# task-3026 — 랭킹·포화도 1,000건 상한 원인 규명 (조사 우선)

**레벨**: Lv.2 · **팀**: dev7-team · **회장 승인 완료** (2026-08-26)
**저장소**: `Jeon-Jonghyuk/InsuRo` (`/home/jay/projects/InsuRo`, 기본 브랜치 **main**)

## ★ 회장 지시
> "3순위는 1천건만 된다는게 좀 걸리긴 한다. 병행 작업으로 원인분석 해내야 함"

**목표는 수치 보정이 아니라 원인 규명이다.** 원인을 특정하지 않은 수정은 완료로 인정하지 않는다.

## 실측 (2026-08-26 06:11 파이프라인 · ANU 확인)
t3019 머지 후 첫 실행에서 경고 3건 → 1건으로 줄었다. 그런데 **숫자가 이상하다.**
```
트렌드 수집    0건    →  32,321건     해소됨
랭킹 산출      0건    →   1,000건     ← 정확히 1,000
포화도      1,000건   →   1,000건     ← 정확히 1,000 (경고 유지)
```
파이프라인 전 단계 `exit=0`, 06:11:24 정상 종료. **경고가 안 뜨는 랭킹이 더 위험하다.**

### 이미 나온 단서 (t3019 조사 산출물 — 검증하고 쓰라, 승계하지 마라)
```
· daily_ranking_calc 에 페이지네이션이 없는 지점 4곳이 지적된 바 있다
· load_trends 가 26,907건 중 1,000건만 읽는다는 관측이 있었다 (3.7%)
· 포화도 경고 자체는 "참"으로 검증된 바 있다 (실제 수집 부족)
```
★ **PostgREST 는 기본 1,000행 상한이 있다.** 결과가 **정확히 1,000**이면 로직이 아니라
**잘림**을 먼저 의심하라. 정확한 총계는 `Prefer: count=exact` + `Range: 0-0` 헤더로 센다.

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

### ① 어디서 잘리는지 특정 (수정 금지 단계)
최근 실행 1회를 기준으로 **표로** 제시하라.
```
| 단계 | 읽어야 할 건수 | 실제 읽은 건수 | 쓴 건수 | 상한에 걸렸나 |
| 트렌드 수집  |  |  |  |  |
| 포화도 수집  |  |  |  |  |
| 랭킹 산출    |  |  |  |  |
```
- 각 단계가 **어떤 쿼리로 몇 건을 읽는지** 실측하라. 코드만 읽고 추정하지 마라
- 총계는 헤더로 정확히 세라. `len(rows)` 는 잘린 뒤의 수라 총계가 아니다

### ② 원인 단정
①의 표에서 어긋나는 지점을 **하나로 특정**하라. 아래를 구분하라.
```
(a) PostgREST/클라이언트 상한에 의한 잘림        → 페이지네이션 문제
(b) 쿼리 조건(기간·필터)이 좁아 실제로 적게 잡힘   → 조건 문제
(c) 상류 수집이 실제로 부족                      → 진짜 부족 (포화도가 여기일 수 있다)
```
★ **셋은 처방이 다르다.** 섞어서 "1,000건 문제"로 뭉뚱그리지 마라.

### ③ 원인에 대응하는 수정
②에서 특정된 것만 고친다.
- 잘림이면 **페이지네이션**을 넣는다(전 지점을 쓸어라. 한 곳만 고치면 다음이 또 잘린다)
- 조건 문제면 조건을 고친다
- 진짜 부족이면 **고치지 말고 보고하라.** 그건 수집 능력 문제이지 코드 버그가 아니다

★ **①②를 건너뛰고 페이지네이션만 넣는 것은 완료로 인정하지 않는다.**

### ④ 조용한 실패를 드러낼 것
지금 랭킹은 **1,000건으로 잘려도 경고가 안 뜬다.** 헬스체크가 "1건 이상"만 보기 때문이다.
- 잘림이 확인되면 **잘렸다는 사실 자체가 경고로 드러나게** 하라
- 오늘 살아난 경보 체계(t3008)가 이걸 못 잡는 것이 문제의 본질이다

## ★ 하지 말 것
- `server/scripts/alert_notify.py` — t3008 결과물. 발송 경로 변경 금지
- `server/scripts/daily_trend_collect.py` · `daily_health_check.py` 의 **t3019 KST 창 로직 변경 금지**
  (기준 산식에 손대야 하면 근거를 대고 ANU 에 먼저 보고하라)
- **DB 데이터 대량 삭제·변경** — 조사는 읽기로. 필요하면 트랜잭션 후 ROLLBACK
- `src/**` · `extension/**` · `server/policy_*` · `server/silson/**`
- 자격증명 값을 저장소에 커밋

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/scripts/daily_ranking_calc.py"
    - "server/scripts/daily_saturation_collect.py"
    - "server/scripts/daily_health_check.py"
    - "server/tests/**"
    - "server/scripts/tests/**"
    - "memory/reports/task-3026.md"
  forbidden_paths:
    - "server/scripts/alert_notify.py"
    - "server/scripts/daily_trend_collect.py"
    - "server/main.py"
    - "server/policy_extract/**"
    - "server/policy_grouping/**"
    - "server/silson/**"
    - "src/**"
    - "extension/**"
    - ".github/workflows/**"
  commands: ["python3", "pytest", "bash"]
  merge_policy: "tiered"
  ttl_hours: 24
```

## 검증
1. **①의 표 제시** — 단계별 읽어야 할 수 / 읽은 수 / 쓴 수 / 상한 여부
2. **원인 단정 근거** — 추정과 확정을 구분해 적어라. (a)(b)(c) 중 무엇인지 명시
3. **수정 후 재실행** — 같은 조건에서 건수가 어떻게 달라지는지 실측 대조
4. **전 지점 확인** — 잘림이 원인이면 **같은 패턴이 남아 있는 곳이 없는지** 전수로 확인하라
5. **봉인** — 페이지네이션을 제거하는 변이를 만들어 테스트가 FAIL 하는지 확인·복원.
   변이가 no-op 이 아님을 `assert` 로 먼저 증명하라
6. **회귀** — `pytest` **base 직접 재측정** 기준선

## 완료 조건 (DoD)
**1,000 이라는 수가 잘림인지 실제 부족인지 단계별로 특정되고, 잘림이면 전 지점이 수정되어
재실행에서 건수가 달라지며, 잘림이 재발하면 경고로 드러난다.**

## ★ 세션 조기 종료 대책
시작 즉시 브랜치 + 드래프트 PR 을 먼저 열어라. **①의 표는 나오는 즉시 PR 본문에 기록하라.**
★ ANU 명세 전제가 틀렸다고 판단되면 구현하지 말고 **반증을 먼저 기록한 뒤 보고하라.**
(t3019 에서 봇이 ANU 의 `total_upserted` 전제를 반증한 것이 옳았다)

## 운영 계약
- `origin/main`(=`14e9596`) 기준 `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 은 **디스크 파일**을 직접 실행한다(`0 6 * * * run_trend_pipeline.sh`).
  `/home/jay/projects/InsuRo` 가 최신인지 확인하라. 병렬 3건 동시 진행 중이다

## 보고
**PR 생성까지가 범위다. 머지는 ANU 가 한다. 자동 머지 금지.**
`memory/reports/task-3026.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"1,000 의 정체 규명 여부((a)잘림/(b)조건/(c)실제부족)"** 를 담아라.