ADR-007 경보 멱등키
결정 risk.alert 에 UNIQUE(rule_code, rule_version, target_key, as_of). 규칙 평가는 INSERT … ON CONFLICT DO UPDATE(근거·메시지 갱신)라 몇 번 다시 돌려도 중복이 없다. as_of 는 기업 2026Q2 · 지역 202607 · 공시 규칙은 접수번호.
상태 관리 (FR-504)
- 기간 규칙: 대상마다 최신 평가 시점에서 참인 경보 하나만 OPEN(사람이 ACK 한 상태는 유지). 과거 시점 경보는 SUPERSEDED, 최신 시점에서 조건이 풀리면 RESOLVED 로 자동 CLOSED.
- 공시 규칙(R-C04): 공시 한 건 = 경보 한 건, 창(windowDays)을 벗어나면 EXPIRED.
- 규칙 버전이 바뀌면 이전 버전의 열린 경보는 RULE_CHANGED.
- DB CHECK 제약으로 빈 근거(
{})는 저장할 수 없다(근거 없는 경보 0).
덧붙임 (2026-10-09, VERIFICATION 118) — ‘모름’은 ‘해소’가 아니다
- 기간 규칙의 기준 시점은 ‘가장 최근 기간’이 아니라 판단할 수 있는 가장 최근 기간이다. 조건은 세 값(참 · 거짓 · 모름)으로 판정한다 —
값이 없거나 상태가 OK 가 아닌 점(MISSING · ZERO_DENOM · NEG_EQUITY · INCONSISTENT)은 모름, 알려진 점 하나가 조건을 깨면 거짓.
- 판단할 수 있는 기간이 하나도 없으면(지표가 통째로 없거나 모두 모름) 경보를 열지도 닫지도 않는다.
- 이유: 실데이터에서 자본잠식(NEG_EQUITY)이 된 분기부터 부채비율 · PF 경보가, 분기 이자비용이 0 이 된 분기부터 이자보상배율 경보가
‘RESOLVED’로 닫혔다 — 위험이 커진 순간에 ‘해소’로 보였다. 바꾼 뒤 같은 데이터에서 3건이 다시 열렸다(사용자 결정 D1).
- 남은 판단: 자본잠식 자체를 위험 신호로 볼지(새 규칙)는 별도 결정.
- 평가 대상(켜진 규칙 × 지금의 대상)에서 빠진 열린 경보는 평가 뒤 닫는다 — 꺼진 규칙은
RULE_DISABLED, 유니버스에서 빠진 기업 · 사라진 지역은
OUT_OF_SCOPE. 대상 목록이 비면(적재 중) 그 종류는 건너뛴다 (VERIFICATION 127).
덧붙임 (2026-10-09, VERIFICATION 139 · 156) — 전이 규칙을 한 곳에
- 무엇을 열고 닫을지는 순수 함수
AlertLifecycle 이 정하고, 서비스는 읽고 쓰기만 한다(단위 테스트로 전이를 고정).
- 기간 규칙의 대체(SUPERSEDED)는 최신 시점에 열 경보가 있을 때만 — 최신 시점이 참이 아니면 과거 시점의 발견이 남아 있어도 해소(RESOLVED).
전에는 대체할 경보가 없는데도 ‘대체’로 닫혔다(139, 이미 그렇게 닫힌 1건은 기존 데이터라 그대로 둠).
- 판단할 수 없어도(위의 ‘모름’) 규칙 버전이 바뀐 옛 버전 경보는 RULE_CHANGED 로 닫는다 — 버전 교체는 판단과 무관. 같은 버전 경보는 그대로(156).