
    S2i+                    :   d Z ddlmZ ddlZddlZddlZddlmZ ddlmZ ej                  j                  d e ee      j                         j                               ddlmZmZmZ ddZddZ	 	 	 	 	 	 	 	 dd	Zed
k(  r ej.                   e              yy)u  G4.4 canary — token-count delta (system.md, tiktoken cl100k_base) (Task 4.5).

Computes baseline (v18) and candidate (v19) token counts for
`prompts/_base/scene_detail/<version>/system.md` and emits the signed delta.

Override O-1 binding gate (signed convention):
  token_delta = candidate_token_count - baseline_token_count
  pass condition: token_delta <= -540  (system-only)
which is mathematically equivalent to baseline - candidate >= 540.

`system_plus_inject_delta <= -150` = secondary report-only metric (no gate).

R3-M2 carry — this script is **CP-free**: it reads prompt files directly
via filesystem and does NOT import the continuity snapshot-hash helper. The
`continuity_card_snapshot_hash` echoed in pinning is operator-supplied and
verified by analyzer cross-check against the 4 metric scripts.

Trap #6 — token gate signed: candidate < baseline ⇒ delta is negative.

Exit criteria (analyzer):
  exit_criteria_pass == True  iff  token_delta <= -540  (default threshold)

Usage (config mode):
    python scripts/canary/g4_4_token_count.py \
        --config canary_config.json \
        --baseline-version 18.202605041549 \
        --candidate-version 19.<timestamp> \
        --output results/g4_4_token_count.json
    )annotationsN)datetime)Path)emit_outputload_pinning_from_argsvalidate_pinningc                 L    t        j                         j                         dz   S )NZ)r   utcnow	isoformat     "scripts/canary/g4_4_token_count.pyiso8601_nowr   0   s    ??&&(3..r   c                 
   t        j                  d      } | j                  dt        d d       | j                  dt        dd	       | j                  d
t        dd	       | j                  dt        dd       | j                  dt        dd       | j                  dt        dd       | j                  dt        d d       | j                  dt        d d       | j                  dt        d        | j                  dt        d        | j                  dt        d        | j                  dt        d        | j                  dt        d g d        | j                  d!t        d        | j                  d"t        d        | j                  d#t        d$       | j                         }t        |      }t        |       g }	 d%d l}|j!                  d*      }t#        |j$                        }||j&                  z  d+z  }	||j(                  z  d+z  }
|	j+                         s|j                  d,|	        |
j+                         s|j                  d-|
        |r?t        |||      }t        ||       |D ]   }t        d'| t        j                  (       " y)	 |	j-                  d./      }|
j-                  d./      }	 t1        |j3                  |            }t1        |j3                  |            }||z
  }||j4                  k  }|j6                  9|j8                  -|j6                  }|j8                  }||z
  }||j:                  k  }nd }d }d }d }i d4t=               d5|d6|j&                  d7|j(                  d8|d9|d:|d;|j4                  d<|d=|d>|d?|d@|j:                  dA|dBdCdD|dEdFdGi}t        ||       t        dH|j&                   dI| dJ|j(                   dI| dK| dL|j4                   dM| dN| dOt        j                  (       |rd%S d)S # t        $ rM d&}|j                  |       t        |||      }t        ||       t        d'| t        j                  (       Y y)w xY w# t.        $ rU}|j                  d0|        t        |||      }t        ||       t        d1| t        j                  (       Y d }~y)d }~ww xY w# t.        $ rU}|j                  d2|        t        |||      }t        ||       t        d3| t        j                  (       Y d }~y)d }~ww xY w)PNzPG4.4 canary: token-count delta (system.md, tiktoken cl100k_base, R3-M2 CP-free).)descriptionz--configzOptional JSON config file path. If provided, overrides individual --baseline-version / --candidate-version / --pid / etc. flags. Mutually exclusive with explicit flags.)typedefaulthelpz--baseline-versionTz=Baseline prompt version directory name (e.g. 18.202605041549))r   requiredr   z--candidate-versionz=Candidate prompt version directory name (e.g. 19.<timestamp>)z--prompt-base-pathzprompts/_base/scene_detailz)Base directory containing version subdirsz--exit-criteria-thresholdizFtoken_delta upper bound for pass (default: -540, Override O-1 binding)z(--system-plus-inject-secondary-thresholdijzGsystem+inject combined delta secondary threshold (report-only, no gate)z--baseline-system-plus-injectzVOptional baseline system+inject token count (operator-supplied, secondary report-only)z--candidate-system-plus-injectzWOptional candidate system+inject token count (operator-supplied, secondary report-only)z--pid)r   r   z--scene-index-listz--shot-index-list-per-scenez--model-routingz--prompt-source-mode)Nfiledb)r   r   choicesz--card-commit-hashz--continuity-card-snapshot-hashz--output)r   r   r   zatiktoken not installed. Install via `pip install tiktoken` (or backend venv). NO silent fallback.z[g4_4_token_count] ERROR: )r      cl100k_basez	system.mdzbaseline system.md not found: zcandidate system.md not found: zutf-8)encodingzprompt file read failed: z3[g4_4_token_count] ERROR: prompt file read failed: ztiktoken encode failed: z2[g4_4_token_count] ERROR: tiktoken encode failed: 	timestamppinningbaseline_versioncandidate_versionbaseline_token_countcandidate_token_counttoken_deltaexit_criteria_thresholdexit_criteria_passsystem_plus_inject_baselinesystem_plus_inject_candidatesystem_plus_inject_delta&system_plus_inject_secondary_threshold!system_plus_inject_secondary_passmeasurement_tooltiktoken cl100k_basemeasurement_failuresmeasurement_scriptstoken_countzcscripts/canary/g4_4_token_count.py (system.md, tiktoken cl100k_base, R3-M2 CP-free, Trap #6 signed)z[g4_4_token_count]
  baseline (z): z tokens
  candidate (z tokens
  token_delta: z.  (signed: candidate - baseline)
  threshold: z<  (pass iff token_delta <= threshold)
  exit_criteria_pass: z
  system_plus_inject_delta: z (secondary report-only))argparseArgumentParseradd_argumentstrint
parse_argsr   r   tiktokenImportErrorappend_failure_outputr   printsysstderrget_encodingr   prompt_base_pathr   r    exists	read_text	Exceptionlenencoder$   baseline_system_plus_injectcandidate_system_plus_injectr)   r   )parserargsr   r-   r6   msgoutencoderbase_dirbaseline_pathcandidate_pathbaseline_textcandidate_textexcr!   r"   r#   	exit_passspi_baselinespi_candidate	spi_deltaspi_secondary_passs                         r   mainrV   4   s|   $$4F B  	 !	   L	   ,8	   #4   2%   '9   (9   c48
,3E
5CN
)TB
$	   ,3E
)T   
t<D$T*GW ') ##M2GD))*Ht444{BM 6 66DN !##,]O<	
   "##-n-=>	
 dG-ABC'C.se43::F (%///A'1171C"7>>-#@A #GNN>$B C (*>>Kt;;;I 	((4--97799!L0	DDD 	 	![]7 	D11 	T33	
 	 4 	 !6 	{ 	"4#?#? 	i 	&| 	' 	#I 	177  	,-?!" 	2#$ 	 4%& 	" 
'C8 T	,,-S
  !../s 
! "% '445 6!!* ,''0k 2"
	# ZZ 1 q   " 	
 	##C(dG-ABC*3%0szzBL  ##&?u$EFdG-ABCA#G	
   ##&>se$DEdG-ABC@F	
 sE   P( #$R 4S" (AQ>=Q>	S
ASS"	U +AT;;U c                    i dt               d|d| j                  d| j                  dd dd dd d| j                  d	d
dd dd dd d| j                  dd ddd|dddiS )Nr   r   r   r    r!   r"   r#   r$   r%   Fr&   r'   r(   r)   r*   r+   r,   r-   r.   r/   zSscripts/canary/g4_4_token_count.py (system.md, tiktoken cl100k_base, R3-M2 CP-free))r   r   r    r$   r)   )rG   r   r-   s      r   r9   r9     s    
[]7 	D11 	T33	
 	 	  	t 	"4#?#? 	e 	&t 	' 	#D 	177  	,T!" 	2#$ 	 4%& 	C 
' r   __main__)returnr3   )rY   r4   )rG   zargparse.Namespacer   dictr-   listrY   rZ   )__doc__
__future__r   r0   jsonr;   r   pathlibr   pathinsertr3   __file__resolveparent_g4_4_commonr   r   r   r   rV   r9   __name__exitr   r   r   <module>rh      s   : #   
   3tH~--/667 8 /e!P
  
	B zCHHTV r   