
    =R4j"                         d Z ddlZddlZddlZddlZdadad Zd Zd Z	dZ
ddd	d
d
dZdZ eg d      ZddZd ZddZddZde
dddZd Zy)uM  
correction_budget.py — ANU v2.13 correction budget ledger (순수 함수, stdlib only)

★ 이 코드는 budget을 reset하지 않는다.
  budget reset 권한은 Chair 전용이며, 코드는 소비/잔액 추적만 수행함.
  IMMEDIATE_CHAIR_AXES 에 해당하는 축은 budget 차감 없이 즉시 Chair 에스컬레이션.
    NFc                  N   t         rt        S 	 t        j                  j	                  t        j                  j                  t                    } t        j                  g d| dd      j                  j                         }|xs d ada t        S # t        $ r d aY da t        S w xY w)N)gitz	rev-parsez--show-toplevelT)cwdcapture_outputtext)_GIT_TOPLEVEL_RESOLVED_GIT_TOPLEVEL_CACHEospathdirnameabspath__file__
subprocessrunstdoutstrip	Exception)heretops     0/home/jay/workspace/scripts/correction_budget.py_git_toplevelr      s    ""#wwrwwx89nn3T
 & 	 "kT "  #"!#s   A9B B$#B$c                      t         j                  j                  d      } | r| S t               }|r|S t        j                         S )NANU_WORKSPACE)r
   environgetr   getcwd)envr   s     r   _resolve_rootr   .   s7    
**..
)C


/C

99;    c                  V    t         j                  j                  t               ddd      S )u<   correction budget ledger 의 기본 경로 (동적 resolve).memorystatezcorrection_budget_ledger.json)r
   r   joinr    r   r   default_ledger_pathr%   8   s#    77<<7,K r               )expected_files_reversibletest_fixture_reportinglocal_runner_wiringruntime_config_touchsystemd_unit_touch)
credential
productionmergecontrol_db_writepromotion_approvalc                 T    t         j                  | d      }|r|rdnt        }||z  }|S )u   
    Parameters
    ----------
    correction_type : str
    same_semantic_axis_repeat : bool
    strong_repeat : bool  — True 이면 페널티 2, False 이면 페널티 1

    Returns
    -------
    int — budget 차감 단위
    r'   r(   )WEIGHTSr   SAME_AXIS_REPEAT_PENALTY)correction_typesame_semantic_axis_repeatstrong_repeatbasepenaltys        r   correction_weightr<   \   s/     ;;*D $!*BKr   c                 6    | xs dj                         t        v S )u6   해당 축이 IMMEDIATE_CHAIR_AXES 에 속하면 True. )lowerIMMEDIATE_CHAIR_AXES)touched_axiss    r   is_immediate_chairrB   r   s    B%%'+???r   c                 T   | 
t               } t        j                  j                  |       sdi iS t	        | dd      5 }|j                         j                         }ddd       sdi iS 	 t        j                  |      S # 1 sw Y   %xY w# t        j                  $ r di icY S w xY w)u   
    ledger JSON 로드. 파일 없거나 비어있으면 {"goals": {}} 반환.

    Parameters
    ----------
    ledger_path : str | None  — None 이면 default_ledger_path() 로 동적 resolve

    Returns
    -------
    dict
    Ngoalsrutf-8encoding)
r%   r
   r   existsopenreadr   jsonloadsJSONDecodeError)ledger_pathfcontents      r   load_ledgerrR   z   s     )+77>>+&}	k3	1 #Q&&(.."#}zz'""# #  }s   B,B B
B'&B'c                    |
t               }t        j                  j                  |      }|rt        j                  |d       |dz   }t        |dd      5 }t        j                  | |dd	
       |j                          t        j                  |j                                ddd       t        j                  ||       y# 1 sw Y    xY w)u  
    ledger dict를 JSON 파일로 atomic 하게 저장 (HIGH 10).
    같은 디렉토리에 tmp 파일을 쓰고 flush + fsync 후 os.replace 로 교체한다.
    쓰기 도중 중단되어도 기존 ledger 가 부분 손상되지 않는다.

    Parameters
    ----------
    ledger : dict
    ledger_path : str | None  — None 이면 default_ledger_path() 로 동적 resolve
    NT)exist_okz.tmpwrF   rG   Fr(   )ensure_asciiindent)r%   r
   r   r   makedirsrJ   rL   dumpflushfsyncfilenoreplace)ledgerrO   dirpathtmp_pathrP   s        r   save_ledgerra      s     )+ggook*G
Gd+V#H	hg	. !		&!%:		
 JJx%	 s   ACC)r8   budgetrO   c          	         |
t               }t        |      }|j                  di       }| |vr| ||i dg d|| <   ||    }|j                  dd      dz   |d<   |j                  di       }	|	j                  |d      dz   |	|<   t	        ||      }
|j                  d|j                  d	|            }||
z
  |d<   |j                  d
g       j                  |||
||d   |d   d       t        ||       t        j                  |      S )uZ  
    goal_id 에 대한 correction budget 소비를 ledger 에 기록하고 entry 반환.

    ★ budget reset 불가 (Chair 전용 권한).
      음수 소진 허용 — clamp 없음 (소진 판정은 is_budget_exhausted 로).

    Parameters
    ----------
    goal_id : str
    signature : str     — diff/tool_calls 서명 (same_signature_retry_count 추적용)
    correction_type : str
    same_semantic_axis_repeat : bool
    budget : int         — 신규 goal 생성 시 초기 budget (기존 entry 에는 무시)
    ledger_path : str

    Returns
    -------
    dict — goal entry
    rD   r   )goal_idrb   budget_remainingsame_signature_retry_countsame_goal_correction_counthistoryrg   r'   rf   )r8   re   rb   rh   )	signaturer7   weightr8   budget_remaining_afterrg   )	r%   rR   
setdefaultr   r<   appendra   copydeepcopy)rd   ri   r7   r8   rb   rO   r^   rD   entrysig_maprj   prev_remainings               r   update_ledgerrs      sH   8 )+%Fgr*E e)0)/)/*,*+)+
g 'NE +0))4PRS*TWX*XE
&';R@G Y2Q6GI ";F YY1599Xv3NON . 7E
 
Y#**$-$3$*%>$)*<$=&+,H&I,  $==r   c                 ,    | j                  dd      dk  S )u+   entry["budget_remaining"] <= 0 이면 True.re   r   )r   )rp   s    r   is_budget_exhaustedru      s    99'+q00r   )FF)N)__doc__rL   r
   rn   r   r	   r   r   r   r%   DEFAULT_BUDGETr5   r6   	frozensetr@   r<   rB   rR   ra   rs   ru   r$   r   r   <module>ry      s     	     "  #$"#"#"#"#   ! "  ,@8&@ $I ^1r   