
    j                    2   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dlmZ ddlmZ dZd	ZdZd
ZdZdZdZdZdZdZdZdZdZddZdddZ	 dedd	 	 	 	 	 	 	 	 	 	 	 d dZd!dZ	 d	 	 	 	 	 	 	 	 	 d"dZ 	 d	 	 	 	 	 	 	 	 	 d"dZ!	 d	 	 	 	 	 	 	 	 	 d"dZ"d#dZ#y)$u  utils.real_merge_artifact_schema — artifact writers + post_smoke schema-only.

task-2637 — real merge executor wiring 코드화 (activation false default · 실제 merge 실행 0).

Spec: memory/specs/system_real_merge_executor_wiring_spec_260523.md §7
sha256: bcaf654e981a43083af50879164021c918eeac9753cad3b3ad146209a1a62765

회장 verbatim (회장 10결정 #6 + spec §7):
    artifact 위치: memory/events/real_merge/<pr>/<head_sha>/
    canonical_root resolver (task-2636) 기준 atomic write
    dedupe (pr + head_sha 동일 → 재호출 0 부작용)

writers (구현):
    * write_merge_decision           → merge_decision.json (schema real_merge.decision.v1)
    * write_pre_merge_gate_snapshot  → pre_merge_gate_snapshot.json
    * write_merge_execution_result   → merge_execution_result.json

schema-only (writer 본 task 범위 외 — pilot 단계에서 구현, 회장 결정 task-2637 expected_files):
    * POST_SMOKE_SCHEMA + POST_SMOKE_REQUIRED_KEYS — 스키마 정의 + validate_post_smoke_payload
    )annotationsN)Path)AnyDictListOptional)atomic_json_write)CANONICAL_ROOT_DEFAULTzreal_merge.decision.v2zreal_merge.decision.v1zreal_merge.pre_gate_snapshot.v1zreal_merge.execution_result.v1zreal_merge.post_smoke.v1)allow_reasonsnapshot_crossrefzmemory/events/real_mergezmerge_decision.jsonzpre_merge_gate_snapshot.jsonzmerge_execution_result.jsonzpost_merge_smoke_result.json)schemats_kstmerge_commit_shaorigin_main_beforeorigin_main_aftersmoke_checksall_okc                    	 t        |       }t        |t              r|st        d      d| d| S # t        t        f$ r t        d|       w xY w)zABuild the ``<pr>/<head_sha>/`` segment with deterministic naming.z pr must be int-convertible, got z#head_sha must be a non-empty stringpr_/)int	TypeError
ValueError
isinstancestr)prhead_shapr_ints      7/home/jay/workspace/utils/real_merge_artifact_schema.py_pr_dirr    F   si    DR h$H>??($$	 z" D;B6BCCDs	   2 Ac           
        |xs t         }t        j                  j                  |      st	        d|      t        j                  j                  t        j                  j                  |t        t        | |                  S )z>Return the absolute directory path for a given (pr, head_sha).z!canonical_root must be absolute: )	r
   ospathisabsr   normpathjoinREAL_MERGE_EVENTS_RELDIRr    )r   r   canonical_rootroots       r   resolve_artifact_dirr*   Q   s`    33D77==<THEFF77BGGLL/GQSU]I^_``    )filename	fs_existsc                   ||nt         j                  j                  }t         j                  j                  t	        | ||      |      }t         ||            S )u   Dedupe check (spec §12.1).

    True if the named artifact already exists for this (pr, head_sha) — caller
    must transition to NO_OP_DUPLICATE without writing or invoking merge.
    )r"   r#   existsr&   r*   bool)r   r   r(   r,   r-   r/   targets          r   artifact_already_presentr2   Y   sI     $/YRWW^^FWW\\R>:HF vr+   c                <    t        |       j                  dd       y )NT)parentsexist_ok)r   mkdir)r#   s    r   _ensure_dirr7   m   s    JTD1r+   c                    t        | ||      }t        |       t        j                  j	                  |t
              }t        |      }|j                  dt               t        ||       |S )u2   Atomic write ``merge_decision.json`` (spec §7.1).r   )
r*   r7   r"   r#   r&   MERGE_DECISION_FILENAMEdict
setdefaultMERGE_DECISION_SCHEMAr	   r   r   payloadr(   out_dirr1   canonical_payloads          r   write_merge_decisionrA   q   sZ     #2x@GWW\\'#:;FW  +@Af/0Mr+   c                    t        | ||      }t        |       t        j                  j	                  |t
              }t        |      }|j                  dt               t        ||       |S )u;   Atomic write ``pre_merge_gate_snapshot.json`` (spec §7.2).r   )
r*   r7   r"   r#   r&   PRE_GATE_SNAPSHOT_FILENAMEr:   r;   PRE_GATE_SNAPSHOT_SCHEMAr	   r=   s          r   write_pre_merge_gate_snapshotrE      sZ     #2x@GWW\\'#=>FW  +CDf/0Mr+   c                    t        | ||      }t        |       t        j                  j	                  |t
              }t        |      }|j                  dt               t        ||       |S )u:   Atomic write ``merge_execution_result.json`` (spec §7.4).r   )
r*   r7   r"   r#   r&   EXECUTION_RESULT_FILENAMEr:   r;   EXECUTION_RESULT_SCHEMAr	   r=   s          r   write_merge_execution_resultrI      sZ     #2x@GWW\\'#<=FW  +BCf/0Mr+   c                P   g }t        | t              sdt        |       j                   gS | j	                  d      t
        k7  r*|j                  dt
        d| j	                  d             t        D ]  }|| vs|j                  d|         | j	                  d      }|7t        |t              s'|j                  dt        |      j                          | j	                  d      }|7t        |t              s'|j                  d	t        |      j                          |S )
u=  Schema-only validator for post_merge_smoke_result.json (spec §7.3).

    Writer is intentionally out of scope for task-2637 (pilot 단계에서 구현).
    This validator exists so the schema contract is fixed *now* — callers can
    author payloads with confidence and the pilot writer will reuse the check.
    zpayload must be dict, got r   zschema must be z, got zrequired key missing: r   z!smoke_checks must be a list, got r   zall_ok must be bool, got )
r   r:   type__name__getPOST_SMOKE_SCHEMAappendPOST_SMOKE_REQUIRED_KEYSlistr0   )r>   errorskeysmoker   s        r   validate_post_smoke_payloadrU      s    Fgt$,T']-C-C,DEFF{{8 11/2&X9N8QR	
 ( :gMM23%89: KK'EE4!89$u+:N:N9OPQ[["F*VT":1$v,2G2G1HIJMr+   )r   r   r   r   returnr   )N)r   r   r   r   r(   Optional[str]rV   r   )r   r   r   r   r(   rW   r,   r   r-   zOptional[Any]rV   r0   )r#   r   rV   None)
r   r   r   r   r>   zDict[str, Any]r(   rW   rV   r   )r>   r   rV   z	List[str])$__doc__
__future__r   r"   pathlibr   typingr   r   r   r   utils.atomic_writer	   utils.callback_envelope_schemar
   r<   MERGE_DECISION_SCHEMA_V1MERGE_DECISION_SCHEMA_V2rD   rH   rN   MERGE_DECISION_V2_OPTIONAL_KEYSr'   r9   rC   rG   POST_SMOKE_FILENAMErP   r    r*   r2   r7   rA   rE   rI   rU    r+   r   <module>rd      s  ( # 	  , , 0 A 1 3 3 < : . #  6  0 ; 9 4  %a %) 
 .#    " 
     
 (2 %)	  "	
 	( %)	  "	
 	( %)	  "	
 	 r+   