
    ej              
          d Z ddlmZ ddlmZmZ ddlmZmZm	Z	 ddl
mZmZmZmZmZ ddlmZmZ dZddZ	 	 	 	 ded
dd	dd	dd	d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZg dZy	)u  dispatch.prompt — task-2386 슬림 prompt facade (task-2388 Phase ε).

dispatch 패키지의 본체는 `dispatch/__init__.py`에 있다.
이 facade는 build_prompt + resume + project_map 영역의 함수만 노출한다.

★ task-2386 슬림 prompt 개선판 보존 — 본체 코드는 무변경.

★ task-2640 (회장 verbatim unfork #3) — prompt 생성 전 ``enforce_callback_owner``
+ ``validate_spawn_callback_contract`` guard 통과를 확인. prompt 텍스트만으로
callback 정책 전달되는 구조 차단. 신규 ``build_prompt_with_contract`` 가
build_prompt 를 감싸고 PASS 시에만 prompt 본문을 반환한다.
    )annotations)OptionalSequence)_inject_project_map_context_resolve_resumebuild_prompt)ANU_KEY_2553COLLECTOR_ROLE_ANUDEFAULT_ANU_KEYSPASSenforce_callback_owner)NO_OP_SPAWN_CONTRACT_FAILED validate_spawn_callback_contractz## ANU chair-facing sessionc                    |s| S ddl m}  ||      s| S t        | xs dv r| S dt         d| d| d}| xs d}|r|j                  d      s|dz   }||z   S )	u  build_prompt 출력 prompt 끝에 chair-facing SID 마커를 append.

    이미 동일 헤더가 존재하면 멱등 (중복 inline 방지). 산출 라인:
        ## ANU chair-facing session
        chair_facing_session_id: <SID>
        callback_resume_required: true
        ★ callback envelope 작성 시 `cokacdir --cron ... --session <SID>` 강제.

    spawn_callback_contract_validator 의 doctrine token 검사는 ANU key + role
    + SELF_COLLECTOR/SENDFILE_ONLY/NOT_REGISTERED 만 본다 → byte-additive 안전.
    r   )is_valid_session_id z

z
chair_facing_session_id: u`   
callback_resume_required: true
★ callback envelope 작성 시 `cokacdir --cron ... --session uB   ` 강제 (★ task-2686 회장 verbatim 2번 / ANCHOR-5 dogfood).

)(dispatch.normal_fallback_callback_helperr   _CHAIR_FACING_SID_HEADERendswith)prompt_textsidr   blockbases        dispatch/prompt.py_inline_chair_facing_sidr   #   s     Ls#K$526
'( )$$'5 )KKN% PE	F 
 "DDMM$'d{%<    Nzspawn-contract-precheckzspawn-contract-precheck-normalTr   )anu_keydispatch_cron_idnormal_collector_cron_idfallback_callback_cron_idno_fallbackanu_keyschat_idchair_facing_session_idc       	           |t        |      nt        t              }t        ||||t        |
||	|dd||      }|j                  t
        k7  rJdd|j                  dt        |j                        t        |j                        t        |j                  |d	S t        | ||||||      }|rt        ||      }t        |||||      }|j                  t
        k7  rTd||j                  |j                  t        |j                        t        |j                        t        |j                  |d	S d	||j                  |j                  g d
g|j                  |dS )u  prompt 생성 전 callback contract 정합성 enforce guard 적용.

    Two-stage gate (텍스트+코드 이중 안전, task md ANCHOR-4):
      1. ``enforce_callback_owner`` — owner 4-tuple 검증 (collector_role=ANU,
         owner != executor, owner is independent ANU key).
      2. ``validate_spawn_callback_contract`` — 산출 prompt 본문이 anu_key
         텍스트 + collector_role + SELF_COLLECTOR/SENDFILE_ONLY/NOT_REGISTERED
         doctrine 토큰을 포함하는지 단언.

    enforce guard 가 PASS 일 때만 실제 build_prompt 호출 결과를 반환한다.
    FAIL 시 ``status: blocked`` + ``no_op_reason`` 반환 → 호출자는 spawn 진입
    자체를 차단해야 함.

    task-2686 ★ chair-facing session propagation (회장 verbatim 2번):
    ``chair_facing_session_id`` 가 명시되면 산출 prompt 마지막에
    ``## ANU chair-facing session`` 헤더로 SID 를 inline 한다. 봇 (executor)
    는 callback envelope 작성 시 ``cokacdir --session <SID>`` 을 자동 첨부할
    수 있다. 미명시면 prompt 변경 0 (byte-0 backwards compatible).

    Returns:
        dict — {
            "status": "ok" | "blocked",
            "prompt": str | None,
            "enforce_verdict": str,
            "contract_verdict": str,
            "classifications": [..],
            "reasons": [..],
            "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED (blocked only),
        }
    NTzdispatch.core.main)task_idexecutor_keycollector_keycollector_owner_keycollector_roler    r!   r   r$   prompt_claims_anu_collector
entry_pathr#   r"   blocked)	statuspromptenforce_verdictcontract_verdictclassificationsreasonsno_op_reasonschemar'   )team_id	task_descr'   level
project_idchain_id	task_type)r'   r(   r   r   r#   oku   build_prompt_with_contract PASS — enforce_callback_owner + validate_spawn_callback_contract 양단 통과 (텍스트+코드 이중 안전).)r/   r0   r1   r2   r3   r4   r6   r'   )tupler   r   r
   verdictr   listr3   r4   r   r6   r   r   r   )r7   r8   r'   r9   r:   r;   r<   r(   r   r   r    r!   r"   r#   r$   r%   keysenforce_resultr0   contract_results                       r   build_prompt_with_contractrD   C   s   b '25?>N8OD ,!#)!9";)$('N %-55 $#N$B$BCN2237$++

 
	
 F )&2IJ6!O $&-55 / 7 7#O$C$CDO3347%,,

 
	
 )11+33_
 "(( r   )r   r   r   rD   r   )r   strr   rE   returnrE   )normalNNcoding)"r7   rE   r8   rE   r'   rE   r9   rE   r:   Optional[str]r;   rI   r<   rE   r(   rE   r   rE   r   rE   r    rI   r!   rI   r"   boolr#   zOptional[Sequence[str]]r$   rE   r%   rI   rF   dict)__doc__
__future__r   typingr   r   dispatchr   r   r    dispatch.callback_owner_enforcerr	   r
   r   r   r   *dispatch.spawn_callback_contract_validatorr   r   r   r   rD   __all__ r   r   <module>rT      s(   # % O O  9 H  $"A  5.N/3(,-1#AAA A 	A
 A A A A A A ,A  -A A &A  !A" +#A$ 
%AHr   