
    Vjc                    ,   d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
 dZ G d dee      Zg d	Z eej                   j"                  ej$                  j"                  h      Zdd
ZddZddZ	 	 	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZddZg dZy)u  utils.source_attribution_guard — Stop hook 사후 거짓표현 차단 가드.

task-2644 ANU_CALLBACK_COLLECTOR_CONTROL_PLANE (회장 verbatim 보강-1 + §15 fixture-8)
spec: memory/specs/system_anu_callback_collector_control_plane_spec_260524.md
spec sha256: b27da557d4245bce476cd63f4ab174aefc8a25d2da07ec2c8d2c83b01ee96153

회장 verbatim 박제 (PR #146 1C0F6F52 사건 2026-05-23 ~00:40 KST):
    schedule_history 사후 조회 결과를 "callback received / 도착 / 수신" 처럼
    inbound 수신으로 흐려 표현한 사건 → Stop hook 으로 사전 차단.

ANCHOR-9: "거짓말 패턴 (수신 vs 사후 조회 흐림) Stop hook 으로 사전 차단".
ANCHOR-11: "source attribution enum 8 (★ CALLBACK_COLLECTOR_PROCESSED 가 주 경로
            · received_inbound 흐림 차단)".

source enum 8 (회장 verbatim 5 → 7 → 8):
    1. RECEIVED_INBOUND_THIS_SESSION
    2. LOG_LOOKUP_AFTER_CHAIR_QUESTION
    3. LOG_LOOKUP_PROACTIVE
    4. MEMORY_RECALL
    5. INFERENCE_ONLY
    6. CALLBACK_COLLECTOR_PROCESSED  (★ task-2644 주 경로)
    7. CALLBACK_LEDGER_RECONCILED  (post-hoc reconciliation)
    8. LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATION  (★ §15 1C0F6F52 박제)
    )annotationsN)Enum)DictListOptionalTuplez!utils.source_attribution_guard.v1c                  0    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zy
)SourceAttributionu)   회장 verbatim 8 enum (보강-1 + §15).RECEIVED_INBOUND_THIS_SESSIONLOG_LOOKUP_AFTER_CHAIR_QUESTIONLOG_LOOKUP_PROACTIVEMEMORY_RECALLINFERENCE_ONLYCALLBACK_COLLECTOR_PROCESSEDCALLBACK_LEDGER_RECONCILED+LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATIONN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r        !utils/source_attribution_guard.pyr
   r
   $   s5    3$C!&G#1#M%N#A !=5 0r   r
   )zcallback receivedu   callback 받았u   callback 도착u   callback 수신u   콜백 도착u   콜백 수신u   콜백 받았zcallback inboundzinbound callbacku   수신 완료u   받음 확인c                p    t        j                  dd| xs d      j                         j                         S )Nz\s+  )resubstriplower)texts    r   
_normaliser"   K   s+    66&#tzr*00288::r   c                T    t        |       }t        D cg c]	  }||v s| c}S c c}w )ub   본문에 inbound 수신 표현이 포함되어 있으면 매칭된 phrase 목록을 돌려준다.)r"   _RECEIVED_PHRASES)r!   
normalisedps      r   contains_received_phraser'   O   s&    D!J(<!AOA<<<s   	%%c                    | t         v S )uA   source 가 inbound 수신을 정당화할 수 있는 enum 인지.)_INBOUND_SOURCES)sources    r   is_inbound_sourcer+   U   s    %%%r   c                V    t        |       }|sdg fS |d|fS t        |      sd|fS d|fS )uj  ANCHOR-9 — "received/도착/수신" 표현 + source attribution 없거나 비 inbound 면 violation.

    Args:
        text: 종료 직전 마지막 user-facing 출력.
        source_attribution: 처리 세션이 명시한 source enum (None = 미명시).

    Returns:
        (violation, matched_phrases). violation=True 이면 Stop hook 종료 차단.
    FT)r'   r+   )r!   source_attributionmatchess      r   detect_received_misuser/   Z   sH     't,Gby!W}/0W}'>r   c                f    |t         j                  j                  k7  ryt        t	        |             S )u  ANCHOR-9 (Stop hook 조건 8) — schedule_history/cron-history 사후 조회를
    inbound 수신처럼 표현하면 fail.

    LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATION source 인데 received phrase 가
    있으면 거짓표현 (1C0F6F52 사건 동일 패턴).
    F)r
   r   valueboolr'   )r!   r-   s     r   "detect_schedule_history_as_inboundr3   q   s1     EEKK (.//r   c                R   |r| rt         j                  j                  S | rt         j                  j                  S |rt         j                  j                  S |rt         j
                  j                  S |rt         j                  j                  S t         j                  j                  S )un  현재 세션 컨텍스트로부터 가장 정확한 source enum 을 분류.

    우선순위 (회장 verbatim 의도):
        1. collector_mode 이고 inbound envelope 있음 → CALLBACK_COLLECTOR_PROCESSED
        2. inbound envelope 있음 → RECEIVED_INBOUND_THIS_SESSION
        3. ledger 만 조회 → CALLBACK_LEDGER_RECONCILED
        4. schedule_history 만 조회 → LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATION
        5. chair 가 물어서 로그 본 경우 → LOG_LOOKUP_AFTER_CHAIR_QUESTION
        6. 그 외 자발적 로그 조회 → LOG_LOOKUP_PROACTIVE
        7. 그 외 → INFERENCE_ONLY
    )r
   r   r1   r   r   r   r   r   )inbound_envelope_presentcollector_modeledger_lookup_onlyschedule_history_lookup_onlychair_question_triggereds        r   classify_sourcer:      s    & 2 ==CCC >>DDD ;;AAA# LLRRR @@FFF++111r   c                    t        | |      \  }}|r|d}nd| d}d|||dS t        | |      rddt        |       |dS ddg |dS )	u   Stop hook 에서 호출하는 정본 진입점.

    Returns:
        {
            "violation": bool,
            "reason": Optional[str],
            "matched_phrases": List[str],
            "source_attribution": Optional[str],
        }
    Nuj   RECEIVED_PHRASE_WITHOUT_SOURCE_ATTRIBUTION (Stop hook 조건 7: '도착/수신' 표현 + source 미명시)z+RECEIVED_PHRASE_NON_INBOUND_SOURCE (source=u=    은 inbound 아님 — 사후 조회를 수신으로 흐림)T)	violationreasonmatched_phrasesr-   u   SCHEDULE_HISTORY_VERIFICATION_AS_INBOUND (Stop hook 조건 8: 1C0F6F52 패턴 — chain status=ok 사후 확인을 수신처럼 표현)F)r/   r3   r'   )r!   r-   misuser.   r=   s        r   validater@      s     -T3EFOFG%R -. /88  &"4	
 	
 *$0BC'  8="4	
 		
 0	 r   )SCHEMAr
   r'   r+   r/   r3   r:   r@   )r!   strreturnrB   )r!   rB   rC   z	List[str])r*   rB   rC   r2   )r!   rB   r-   Optional[str]rC   zTuple[bool, List[str]])r!   rB   r-   rD   rC   r2   )r5   r2   r6   r2   r7   r2   r8   r2   r9   r2   rC   rB   )r!   rB   r-   rD   rC   zDict[str, object])r   
__future__r   r   enumr   typingr   r   r   r   rA   rB   r
   r$   	frozensetr   r1   r   r)   r"   r'   r+   r/   r3   r:   r@   __all__r   r   r   <module>rJ      s   0 # 	  . . 
-T    77==66<< ;=&

% .02"2 2 	2
 #'2 #2 	2@.b	r   