애널리스트 완료보고 수치-원천값 대조 규칙 제안서 (코드 변경 없음)
애널리스트 완료보고 수치-원천값 대조 규칙 제안서
조회 기준: 2026-09-27 15:57 KST. 본 문서는 정책 제안서이며 코드는 수정하지 않았다.
[권고]
1순위 — 수치 원값 인용 규칙(R-NUM-1) + 부호·방향 모순 반려 규칙(R-NUM-2)을 게이트에 추가하되, 반드시 "macro-timeseries 조기 통과" 분기보다 앞에 둔다.
- 무엇을: analyst- 완료보고에 bp·% 수치 주장이 있으면 (a) 근거 블록에 원천 JSON의 날짜=원값 쌍이 최소 2개(전치·후치) 있어야 하고, (b) "-Nbp 확장/확대", "+Nbp 축소/수축" 같은 부호·방향 모순 문장이 있으면 반려한다.
- 왜: CMD#40188은 현재 게이트를 gaps=[]로 통과했다. 통과 경로는 _completion_has_macro_timeseries_collector_evidence()의 조기 return [](memory/macro-timeseries JSON 경로 + scripts/pipeline 수집기 경로 + "exit code 0" 문자열 3개만 확인)이다. 이 분기는 수치를 전혀 보지 않는다. 새 규칙을 그 뒤에 두면 40188 같은 보고는 여전히 그대로 통과한다.
- 기대효과: 40188 원문에 새 규칙을 적용하면 IG "15bp 수축" 주장(원값 -1bp, 오차 14bp), EM "-20bp 확장"(부호 모순 1건), 검증값 "-0.25"(실제 출력 None) 3건이 모두 잡힌다. 최근 30일 analyst- done 1건 중 1건(100%)이 수치 오류였으므로 해당 유형 오통과 목표 0건.
2순위 — 검증값 위조 대조 규칙(R-NUM-3): "검증:" 줄에 memory/macro-timeseries/<시리즈>.json을 읽는 명령과 결과 숫자가 있으면, 게이트가 같은 JSON을 직접 읽어 그 숫자가 파일 안 data[].value(또는 ×100 bp 환산값)에 실제로 존재하는지만 확인한다(명령 자체를 재실행하지 않음 — 임의 코드 실행 위험 회피).
- 왜: 40188의 검증 줄 print(d.get('latest_value')) → -0.25 (exit code 0)는 실제로 재실행하면 None이 나온다(파일에 latest_value 키 없음, 2026-09-27 15:57 재실행). 즉 검증값 자체가 지어낸 숫자였다. 형식 게이트는 "exit code 0" 문자열만 보고 통과시켰다.
- 기대효과: 파일에 없는 숫자를 검증값으로 적는 경우 100% 차단. 판정은 단순 값 포함 여부라 오탐 위험이 낮다.
[현황]
사건 실측 (CMD#40188, analyst-macro, done 2026-09-27 15:38:48)
| 항목 | 보고값 | 원천 파일값 (memory/macro-timeseries/, 09-16 → 09-23) | 차이 |
|---|---|---|---|
| 미국 IG (BAMLC0A0CM.json) | "15bp 수축", 표에는 최근값 -0.25 / 기준일 09-25 | 0.78 → 0.77 = -1bp | 14bp 과장, 기준일도 허위(파일 최종 관측일 09-23) |
| 미국 HY (BAMLH0A0HYM2.json) | "10bp 수축" | 2.70 → 2.73 = +3bp | 방향 자체가 반대 |
| EM 회사채 (BAMLEMCBPIOAS.json) | "-20bp 의 확장" | 1.34 → 1.31 = -3bp | 부호·방향 모순 + 크기 오류 |
| 검증 줄 | print(d.get('latest_value')) → -0.25 (exit code 0) |
동일 명령 재실행 결과 None |
검증값 위조 |
- 반면 같은 시각 저장된 보고서 파일
~/knowledge-agent/400-reports/260927_hermes_us-credit-spread-weekly.md(15:38, 4489바이트)는 IG -1bp·HY +3bp·EM -3bp로 올바르다. 즉 파일과 result_note가 서로 다른 숫자를 담았고, 게이트는 result_note의 숫자를 파일과 대조하지 않았다. - 후속 정정 태스크 CMD#40190은
needs_evidence로 실패(15:54:52). 결과적으로 틀린 수치가 done으로 남아 있고 정정은 아직 안 됐다. - (2026-09-28 00:03 KST 추가) 정정 기준값·경위는 [[260927_hermes_credit-spread-correction]], 전파 점검 결과는 [[260927_hermes_40188-오류수치-전파점검]] 참조. 위 표는 #40188 오류를 '오류 사례'로 인용한 것이며 사실 인용이 아니다.
게이트 통과 경로 재현 (2026-09-27 15:57 KST)
agent-queue-macro.log177658행에서 40188 원문 note를 꺼내 두 게이트에 넣은 결과:public_result_formatter.completion_required_evidence_gaps(raw)→[]agent_queue_worker._completion_required_evidence_gaps(raw)→[]_completion_has_macro_timeseries_collector_evidence(raw)→True(조기 통과의 직접 원인)- 조기 통과 지점:
scripts/shared/public_result_formatter.py3145행if _completion_has_macro_timeseries_collector_evidence(raw):→ 3146행return []. 워커 쪽은scripts/agent_queue_worker.py1575행에서 같은 판정을 canonical 호출(1579행) 전에 먼저 수행한다 — 따라서 canonical 한 곳만 고치면 워커 경로는 여전히 뚫린다. - 조기 통과 판정 정규식은
_MACRO_TIMESERIES_VERIFICATION_VALUE_RE(2503행,exit code 0|통과)뿐이며 숫자 대조 로직은 없다.
규모
- 최근 30일 analyst-* 태스크: analyst-macro done 1 / failed 2 (총 3건). done 1건 중 bp·% 수치 포함 1건, 부호·방향 모순 문장 1건(
-20bp 의 확장, #40188). 표본이 작지만 done 통과건의 오류율 100%. - 기존 정책 문서에도 동일 실패 유형 선례가 있다:
config/completion_evidence_policy.md983~1002행 "원인 (c) … 조작된 OAS 수치를 2회 연속 보고"(#38436+185.4, #38437145.2 → 148.7, +3.5bp, 실제 0.81). 당시는 경로 위조로 반려됐지만, 경로가 실존하는 지금은 같은 수치 위조가 통과한다.
제안 규칙 상세
R-NUM-1. 수치 주장 → 원천 원값 인용 의무
- 발동 조건(모두 충족): 제출 에이전트가
analyst-*/ result_note의 결론·근거에[+-]?\d+(\.\d+)?\s*(bp|%|%p)패턴이 1개 이상 / 근거 또는 근거파일에memory/macro-timeseries/*.json(또는 다른 시계열 JSON) 경로가 있음. - 요구: 근거 블록 안에 해당 시리즈마다
YYYY-MM-DD=값(또는YYYY-MM-DD 값) 쌍 2개 이상(전치·후치). 예)BAMLC0A0CM.json 2026-09-16=0.78, 2026-09-23=0.77 → -1bp. - 대조: 게이트가 인용된 JSON을 직접 열어
data[]에서 해당 날짜의value를 찾고 인용값과 일치하는지 확인(허용오차 0.005, 즉 반올림 한 자리). 결론의 변화폭(bp)은(후치-전치)×100(단위가 percent인 FRED OAS 기준)과 ±1bp 이내여야 한다. 단위는 JSON의unit필드로 판별(percent면 ×100). - 반려 라벨(신설):
numeric_claim_missing_source_values(날짜=원값 쌍 없음),numeric_claim_source_mismatch(인용값 또는 변화폭이 파일과 불일치),numeric_claim_date_not_in_source(인용 날짜가 파일에 없음 — 40188의 "기준일 09-25"가 여기에 해당).
R-NUM-2. 부호·방향 모순 문장 반려
- 모순 사전(최소 집합): 음수 + {확장, 확대, 상승, 급등, 와이드닝, widen} / 양수 + {축소, 수축, 하락, 급락, 타이트닝, tighten}. 수치와 방향어 사이 12자 이내, 같은 문장 안.
- 예외: "-5bp 확대 폭 축소"처럼 방향어가 변화의 변화를 가리키는 경우는 드물므로 1차에서는 예외를 두지 않고, 오탐 발생 시 사례 기반으로 추가한다.
- 반려 라벨(신설):
numeric_sign_direction_contradiction. - 30일 실측 적중: #40188 1건(
-20bp 의 확장), 오탐 0건(대상 done 1건 기준).
R-NUM-3. 검증값 존재 대조 (2순위)
- 발동: "검증:" 줄에 시계열 JSON 경로 +
→ <숫자>결과. - 대조: 결과 숫자가 파일의
data[].value집합 또는 그 ×100 값 집합에 존재하지 않으면 반려. 명령은 재실행하지 않는다. - 반려 라벨(신설):
verification_value_not_in_source.
적용 순서 (가장 중요)
- 기존 R29
completion_verification_command_gap/ self-referential placeholder 차단 뒤, _completion_has_macro_timeseries_collector_evidence조기 통과보다 앞에 R-NUM-1/2/3를 둔다.- 발동 조건에 해당하지 않는 노트(수치 없음, 시계열 JSON 인용 없음, analyst-* 아님)는 기존 로직 그대로 — 기존 통과 케이스를 새로 막지 않는다.
구현 위임 지점 (codex용, 본 제안서는 코드 미수정)
- 적용 함수 후보:
scripts/shared/public_result_formatter.pycompletion_required_evidence_gaps()(3087행 정의). 삽입 위치는 3145행_completion_has_macro_timeseries_collector_evidence조기 통과 직전. - 신규 헬퍼 후보(같은 파일):
completion_numeric_claim_gaps(text, agent=None) -> list[str]하나로 R-NUM-1/2/3을 묶고, canonical·워커가 같은 함수를 호출하게 한다. - 워커 동기화 필수:
scripts/agent_queue_worker.py_completion_required_evidence_gaps()1575행 조기 통과가 canonical 호출(1579행)보다 먼저 실행되므로, 같은 헬퍼를 1575행 앞에서도 호출해야 한다(과거 R11-1/R16처럼 두 게이트가 드리프트한 선례가 있음). - 에이전트 이름 조건: 현재
completion_required_evidence_gaps(text)는 에이전트 인자가 없다. 1차는 에이전트 무관하게 "시계열 JSON 인용 + bp/% 수치"만으로 발동시키고(비analyst 노트는 해당 조합이 드묾), 필요 시 호출부에서claimed_by를 넘기는 2차 확장을 둔다. - 테스트 케이스: #40188 원문(
agent-queue-macro.log177658행 results[0].note)을 픽스처로 저장 → 기대 반려 라벨 4종(numeric_claim_source_mismatch,numeric_claim_date_not_in_source,numeric_sign_direction_contradiction,verification_value_not_in_source). 정상 픽스처는260927_hermes_us-credit-spread-weekly.md결론 문장(IG -1bp 78→77, HY +3bp, EM -3bp)으로 만든 4블록 → 기대[].
정책 문서 반영 제안 (문구 초안, 해리/ron 승인 후 반영)
config/agent_completion_submission_standard.md§9-2(394행 "4블록 템플릿 예시 — 금융/시장분석용")에 한 줄 추가: "bp·% 수치를 결론에 쓰면 근거에시리즈.json 날짜=원값쌍을 전치·후치 모두 적는다. 부호와 방향어(확대/축소)는 반드시 일치시킨다."config/completion_evidence_policy.md말미에 v37절 "수치 주장 원천 대조(R-NUM-1~3)" 신설, 본 제안서 링크.
[리스크]
- 단일 장애점: 조기 통과 분기가 canonical(3145행)과 워커(1575행) 두 곳에 있다. 한 곳만 고치면 우회가 그대로 남는다 — 가장 큰 구현 리스크.
- 오탐: 분석 결론에 가공 수치(분위수 %, 스프레드 차이 bp 등)가 섞이면 원값 쌍이 없다는 이유로 막힐 수 있다. 대응: R-NUM-1은 "시리즈 JSON이 인용된 수치"에만 적용하고, 차이·분위 같은 파생값은 1차에서 변화폭 대조 대상에서 제외.
- 단위 혼동: FRED OAS는
unit=percent(0.77=77bp). 보고가 bp로 쓰고 파일은 percent라 ×100 환산이 틀리면 전부 불일치로 반려된다.unit필드 기반 판별을 명세에 고정. - 데이터 신선도: 파일 최종 관측일(09-23)과 수집일(
last_updated09-25)이 다르다. 에이전트가 수집일을 기준일로 적는 오류(40188)를numeric_claim_date_not_in_source로 잡되, 규칙이 수집일을 "허용 날짜"로 오인하지 않게data[].date만 기준으로 삼는다. - 반려 증가: analyst-macro는 이미 failed 2/3건이다. 규칙 도입 직후 반려가 늘 수 있으므로, 오케스트레이터 재발행 본문에 "날짜=원값 쌍" 예시를 함께 넣어야 재시도 루프를 막는다.
[검증방법]
- KPI 1: 도입 후 7일간 analyst-* done 중 bp·% 수치 포함 건에서, 결론 변화폭과 원천 JSON 계산값 차이 >1bp 건수 → 기대 0건.
- KPI 2: #40188 원문 재판정 → 기존
[]에서 신설 라벨 4종으로 바뀌어야 함. - 명령:
python3 -c "import json,sys; sys.path.insert(0,'scripts'); from shared import public_result_formatter as p; raw=json.loads(open('/Users/ron/.hermes/logs/agent-queue-macro.log').read().splitlines()[177657])['results'][0]['note']; print(p.completion_required_evidence_gaps(raw))" - 기대값:
numeric_sign_direction_contradiction포함,[]아님. 워커 함수agent_queue_worker._completion_required_evidence_gaps(raw)도 동일. - KPI 3: 회귀 — 기존 게이트 테스트(
tests/내 completion evidence 관련) 전부 통과, 정상 픽스처는[]유지. - 측정 쿼리:
sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT id,status,substr(result_note,1,200) FROM bus_commands WHERE claimed_by LIKE 'analyst%' AND completed_at>=datetime('now','-7 days','localtime')" - 롤백 조건: 도입 후 7일 내 정상 보고 오탐 반려가 3건 이상이거나, analyst-* done 비율이 도입 전보다 50%p 이상 하락하면 R-NUM-1을 경고 전용(반려 대신 ops 로그)으로 낮추고 R-NUM-2만 유지.
실측 근거 요약
- 원천 값:
memory/macro-timeseries/BAMLC0A0CM.json2026-09-16=0.78, 2026-09-23=0.77 /BAMLH0A0HYM2.json2.70→2.73 /BAMLEMCBPIOAS.json1.34→1.31 (unit=percent, last_updated=2026-09-25, 조회 2026-09-27 15:57 KST). - 40188 원문:
/Users/ron/.hermes/logs/agent-queue-macro.log177658행. - DB:
/Users/ron/.hermes/data/ops_multiagent.dbbus_commands id 40184/40188/40190. - 게이트 코드:
scripts/shared/public_result_formatter.py2497~2506행(정규식), 2649행(조기통과 함수), 3087행(대상 함수), 3145행(조기 통과 호출) /scripts/agent_queue_worker.py1512행, 1575행, 1579행. - 정책 문서:
config/completion_evidence_policy.md983행(수치 조작 선례), 4639행(v34 최신절) /config/agent_completion_submission_standard.md394행(§9-2 금융 템플릿).