§
    ¬	Êjjá  ã                  ó  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZ ddlmZ  ee¦  «                             ¦   «         j        Z ej        ¦   «         ZdZdZdZd	ad
adfd„Zd\  ZZZZ Z!dZ"dt4          › d�a# ej$        d¦  «        Z% e&h d£¦  «        Z' G d„ de(¦  «        Z) G d„ de(¦  «        Z*dgd„Z+dhd„Z,did#„Z-djd%„Z.dkd'„Z/dld+„Z0dmd0„Z1dnd1„Z2dod3„Z3dnd4„Z4dpd7„Z5dqd;„Z6drdB„Z7dsdC„Z8dtdE„Z9dudI„Z:dvdL„Z;dwdO„Z<dPZ=dQZ>dxdR„Z?dydS„Z@dzdT„ZAd{dU„ZBd{dV„ZCd{dW„ZDd{dX„ZEd|dZ„ZFd}d[„ZGd~d\„ZHdd^„ZId€d�d`„ZJd‚da„ZK G db„ dcejL        ¦  «        ZMd€d{dd„ZNeOdek    r e	jP         eN¦   «         ¦  «         dS dS )ƒa¹  The publish gate, for every package that pins this one.

Written for three packages - invisible_core, invisible_playwright and
invisible_firefox; the last was deleted on 2026-08-18, and the gate below is
unchanged by that, because it was never named to a fixed count of consumers -
see "one gate on purpose" below.

Importable, so `python -m invisible_core.release` works wherever the core is
installed - which is everywhere, since every consumer pins it exactly. It used
to be a script in the core's repo, so the consumers had no gate at all: on
2026-07-27 invisible-playwright 0.4.4 reached the index built from a tree that
predated the fix it was supposed to carry, uploaded by a bare `twine upload` of
whatever happened to be in a directory. A PyPI filename is never re-uploaded, so
that artifact is wrong forever and the only remedy was 0.4.5.

`publish` builds and uploads WHAT IT JUST BUILT. That is the property which makes
that failure impossible, and it is the reason to use this rather than twine - not
the digests, not the ledger, but that the bytes uploaded are the bytes the gate
looked at.

Which project is gated comes from the pyproject.toml at --project-root, so this
file names no package.
é    )ÚannotationsN)ÚdatetimeÚtimezone)ÚPathzPUBLISHED.jsoné   zCHANGELOG.mdzinvisible-coreÚinvisible_coreÚrootú'Path'Úreturnú'tuple[str, str]'c                ó$  — t          | ¦  «        dz  }	 ddl}|                     d¦  «        5 }|                     |¦  «        }ddd¦  «         n# 1 swxY w Y   n(# t          $ r}t          d|› d|› �¦  «        |‚d}~ww xY wt          |                     di ¦  «                             d¦  «        pd	¦  «                             ¦   «         }|st          |› d
�¦  «        ‚|                     di ¦  «                             di ¦  «                             di ¦  «                             di ¦  «                             di ¦  «                             d¦  «        pg }|rt          |d         ¦  «        j	        n| 
                    dd¦  «        }||fS )a   (distribution name, wheel package name) read from the project itself.

    From pyproject rather than from an argument: a name passed on the command
    line is a second place for it to be wrong, and this gate exists to stop that
    class of mistake.
    zpyproject.tomlr   NÚrbzcannot read ú: ÚprojectÚnameÚ z declares no [project] nameÚtoolÚhatchÚbuildÚtargetsÚwheelÚpackagesú-Ú_)r   ÚtomllibÚopenÚloadÚ	ExceptionÚ
GateBrokenÚstrÚgetÚstripr   Úreplace)	r	   Úcfg_pathr   ÚfhÚcfgÚexcÚdistr   Úpkgs	            úFC:\Projects\Muse2API\.venv\Lib\site-packages\invisible_core/release.pyÚresolve_project_identityr+   C   sÔ  € õ �D‰zŒzÐ,Ñ,€HðDØˆˆˆØ�]Š]˜4Ñ Ô ð 	# BØ—,’,˜rÑ"Ô"ˆCð	#ð 	#ð 	#ñ 	#ô 	#ð 	#ð 	#ð 	#ð 	#ð 	#ð 	#øøøð 	#ð 	#ð 	#ð 	#øøåð Dð Dð DÝÐ9¨Ð9Ð9°CÐ9Ð9Ñ:Ô:ÀÐCøøøøðDøøøåˆs�wŠw�y "Ñ%Ô%×)Ò)¨&Ñ1Ô1Ð7°RÑ8Ô8×>Ò>Ñ@Ô@€DØð CÝ˜HÐAÐAÐAÑBÔBÐBØ—’˜ Ñ#Ô#×'Ò'¨°Ñ4Ô4×8Ò8¸À"ÑEÔEß’C˜	 2Ñ&Ô&§s¢s¨7°BÑ'7Ô'7¿º¸J¹¼ðNØKMð à$,Ð
H�$ˆx˜Œ{Ñ
Ô
Ô
 Ð
 °$·,²,¸sÀCÑ2HÔ2H€CØ�ˆ9Ðs:   ”A ­AÁA ÁAÁA ÁAÁA Á
B Á%A;Á;B )r   r   é   é   é   é   úhttps://pypi.org/pypi/ú/jsonz^(\d+)\.(\d+)\.(\d+)$>   ú.hgtagsú	.hgignoreú
.gitignoreú.gitattributesc                  ó   — e Zd ZdZdS )r   z4The gate could not form an opinion. Never a refusal.N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    r*   r   r   y   s   € € € € € Ø>Ð>Ð>Ð>r=   r   c                  ó   — e Zd ZdZdS )ÚLedgerUnavailablezJThe gate's memory is missing or unreadable. Never a pass, never a refusal.Nr7   r<   r=   r*   r?   r?   }   s   € € € € € ØTÐTÐTÐTr=   r?   ÚbÚbytesr    c                óN   — t          j        | ¦  «                             ¦   «         S ©N)ÚhashlibÚsha256Ú	hexdigest)r@   s    r*   Ú_sha256_bytesrG   ƒ   s   € ÝŒ>˜!ÑÔ×&Ò&Ñ(Ô(Ð(r=   Úblobc                ó´   — d| v r| S 	 |                       d¦  «         n# t          $ r | cY S w xY w|                      dd¦  «                             dd¦  «        S )aô  Fold CRLF and lone CR to LF for anything that is text.

    A checkout on Windows with autocrlf active and the same checkout on Linux
    hold the same content in different bytes. The ledger is checked in and
    travels between the two, so digesting raw bytes would make the first CI run
    on Linux refuse a release nobody made a change to. Binary payloads are left
    exactly alone: a NUL byte or a failed UTF-8 decode is the test, and both are
    conservative - misjudging a text file as binary costs a false alarm, the
    error this normalisation exists to remove, so the test errs towards text
    only when the bytes really do decode.

    THE EXACT BOUNDARY, both sides of it deliberate
    -----------------------------------------------
    This is the only place the gate is allowed to be blind, so the width is
    chosen rather than inherited, and both edges are pinned by tests
    (test_release_gate.py, D4 and D6):

      lower edge - it must fold at least CRLF, or the gate cries wolf on every
        cross-platform release and gets switched off.
      upper edge - it must fold nothing ELSE. Every other whitespace difference
        survives: an extra space, a tab, a blank line, a trailing newline and,
        above all, a change of indentation. Indentation is semantic in Python,
        so a normalisation that stripped whitespace generally would let a
        re-indent - which can move a statement out of an `if` - ship under an
        unchanged version.

    THE COST, accepted knowingly
    ----------------------------
    A lone CR is folded wherever it appears, including inside a string literal
    where it is DATA and not a line ending. A build whose only difference is
    `"a\rb"` becoming `"a\nb"` therefore reads as byte-identical here and the
    gate will not refuse it. The alternative is to tell a content CR apart from
    a line-ending CR without parsing the language the file is written in, which
    cannot be done; digesting raw bytes instead brings back the false alarm on
    every CRLF checkout, which is the worse failure because it ends with the
    gate turned off. Source that genuinely needs a bare CR should write the
    escape `\r` rather than embed the byte, and then it is ordinary text and is
    digested like any other.
    ó    úutf-8ó   
ó   
ó   )ÚdecodeÚUnicodeDecodeErrorr#   )rH   s    r*   Ú	normaliserQ   ‡   su   € ðP �$€€ØˆðØ�Š�GÑÔÐÐøÝð ð ð Øˆˆˆðøøøà�<Š<˜ Ñ'Ô'×/Ò/°°uÑ=Ô=Ð=s   ˆ ž-¬-Úwhlr   údict[str, str]c           	     ó¶  — i }t          j        | ¦  «        5 }d„ |                     ¦   «         D ¦   «         }t          |¦  «        dk    rt	          | j        › d|› �¦  «        ‚|d                              dd¦  «        d         dz   }|                     ¦   «         D ]Œ}|                     ¦   «         rŒ|j	        }||d         k    rŒ+| 
                    |¦  «        rd|t          |¦  «        d…         z   }t          t          |                     |¦  «        ¦  «        ¦  «        ||<   Œ�	 ddd¦  «         n# 1 swxY w Y   |st	          | j        › d�¦  «        ‚|S )	an  path -> sha256 of each member's normalised bytes.

    Hashed here rather than copied out of RECORD: RECORD carries the raw byte
    digest, which is exactly the number a CRLF/LF flip moves. RECORD itself is
    skipped - its bytes are a function of every other member, so including it
    would just re-report the same differences a second time, un-normalised.
    c                ó<   — g | ]}|                      d ¦  «        ¯|‘ŒS )z.dist-info/RECORD©Úendswith©Ú.0Úns     r*   ú
<listcomp>z"wheel_manifest.<locals>.<listcomp>Â   s*   € ÐSÐSÐS˜a°1·:²:Ð>QÑ3RÔ3RÐS˜ÐSÐSÐSr=   r   z%: expected exactly one RECORD, found r   ú/z<dist-info>/Nz: the wheel holds no files)ÚzipfileÚZipFileÚnamelistÚlenr   r   ÚrsplitÚinfolistÚis_dirÚfilenameÚ
startswithrG   rQ   Úread)rR   ÚoutÚzÚrecord_namesÚ	dist_infoÚinfor   s          r*   Úwheel_manifestrl   ¸   sŸ  € ð €CÝ	Œ˜Ñ	Ô	ð ? ØSÐS 1§:¢:¡<¤<ÐSÑSÔSˆÝˆ|ÑÔ Ò!Ð!Ý ¤Ð]Ð]È|Ð]Ð]Ñ^Ô^Ð^Ø  ”O×*Ò*¨3°Ñ2Ô2°1Ô5¸Ñ;ˆ	Ø—J’J‘L”Lð 
	?ð 
	?ˆDØ�{Š{‰}Œ}ð ØØ”=ˆDØ�| A”Ò&Ð&Øð �Š˜yÑ)Ô)ð >Ø%¨­S°©^¬^¨_¨_Ô(=Ñ=�Ý%¥i°·²°t±´Ñ&=Ô&=Ñ>Ô>ˆC�‰IˆIð
	?ð?ð ?ð ?ñ ?ô ?ð ?ð ?ð ?ð ?ð ?ð ?øøøð ?ð ?ð ?ð ?ð  ð BÝ˜CœHÐ@Ð@Ð@ÑAÔAÐAØ€Js   —DD5Ä5D9Ä<D9Úsdistc                óø  — i }t          j        | d¦  «        5 }|                     ¦   «         D ]›}|                     ¦   «         sŒd|j        v r!|j                             dd¦  «        d         n|j        }|t          v rŒR|                     |¦  «        }|€Œjt          t          | 
                    ¦   «         ¦  «        ¦  «        ||<   Œœ	 ddd¦  «         n# 1 swxY w Y   |st          | j        › d�¦  «        ‚|S )zFpath -> sha256 for every regular file, top-level version dir stripped.zr:gzr\   r   Nz
: no files)Útarfiler   Ú
getmembersÚisfiler   ÚsplitÚSDIST_NONCONTENTÚextractfilerG   rQ   rf   r   )rm   rg   ÚtfÚmemberr   r%   s         r*   Úsdist_manifestrw   Ö   s<  € à€CÝ	Œ�e˜VÑ	$Ô	$ð 
<¨Ø—m’m‘o”oð 		<ð 		<ˆFØ—=’=‘?”?ð ØØ36¸&¼+Ð3EÐ3E�6”;×$Ò$ S¨!Ñ,Ô,¨QÔ/Ð/È6Ì;ˆDØÕ'Ð'Ð'ØØ—’ Ñ'Ô'ˆBØˆzØÝ%¥i°·²±	´	Ñ&:Ô&:Ñ;Ô;ˆC�‰IˆIð		<ð
<ð 
<ð 
<ñ 
<ô 
<ð 
<ð 
<ð 
<ð 
<ð 
<ð 
<øøøð 
<ð 
<ð 
<ð 
<ð ð 4Ý˜EœJÐ2Ð2Ð2Ñ3Ô3Ð3Ø€Js   ˜B1CÃCÃCÚmanifestc                ó¤   ‡ — d                      ˆ fd„t          ‰ ¦  «        D ¦   «         ¦  «        }t          |                     d¦  «        ¦  «        S )Nú
c              3  ó2   •K  — | ]}|› d ‰|         › �V — ŒdS )ú,Nr<   )rY   Úprx   s     €r*   ú	<genexpr>z"manifest_digest.<locals>.<genexpr>ê   s5   øè è € ÐDÐD¨a˜Ð)Ð)˜H QœKÐ)Ð)ÐDÐDÐDÐDÐDÐDr=   rK   )ÚjoinÚsortedrG   Úencode)rx   rH   s   ` r*   Úmanifest_digestr‚   é   sK   ø€ Ø�9Š9ÐDÐDÐDÐDµ6¸(Ñ3CÔ3CÐDÑDÔDÑDÔD€DÝ˜Ÿš WÑ-Ô-Ñ.Ô.Ð.r=   ÚoldÚnewúdict[str, list[str]]c                ód  ‡ ‡— t          ˆˆ fd„‰                      ¦   «         ‰                     ¦   «         z  D ¦   «         ¦  «        t          ‰                     ¦   «         ‰                      ¦   «         z
  ¦  «        t          ‰                      ¦   «         ‰                     ¦   «         z
  ¦  «        dœS )Nc              3  ó@   •K  — | ]}‰|         ‰|         k    ¯|V — Œd S rC   r<   )rY   r}   r„   rƒ   s     €€r*   r~   z!diff_manifests.<locals>.<genexpr>ð   s5   øè è € ÐQÐQ ÀÀAÄÈ#ÈaÌ&Ò@PÐ@P˜!Ð@PÐ@PÐ@PÐ@PÐQÐQr=   ©ÚchangedÚaddedÚremoved)r€   Úkeys)rƒ   r„   s   ``r*   Údiff_manifestsr�   î   s‹   øø€ åÐQÐQÐQÐQÐQ S§X¢X¡Z¤Z°#·(²(±*´*Ñ%<ÐQÑQÔQÑQÔQÝ˜Ÿš™
œ
 S§X¢X¡Z¤ZÑ/Ñ0Ô0Ý˜#Ÿ(š(™*œ* s§x¢x¡z¤zÑ1Ñ2Ô2ðð ð r=   ÚoutdirÚisolatedÚboolútuple[Path, Path]c           
     ó¾  — t           j        dddddt          |¦  «        t          | ¦  «        g}|s|                     dd¦  «         t	          j        |dd¬	¦  «        }|j        d
k    rd|j        p|j        pd 	                    ¦   «          
                    ¦   «         dd …         }t          dd                     |¦  «        z   dz   ¦  «        ‚t          |                     d¦  «        ¦  «        }t          |                     d¦  «        ¦  «        }t          |¦  «        dk    st          |¦  «        dk    rt          d|› d|› d|› �¦  «        ‚|d
         |d
         fS )Nú-mr   z--wheelz--sdistz--outdirr.   z--no-isolationT)Úcapture_outputÚtextr   r   iñÿÿÿz4the build failed, so there is nothing to compare:
  z
  z8

If the backend is missing: pip install build hatchlingz*.whlz*.tar.gzr   z$expected one wheel and one sdist in z, got ú )ÚsysÚ
executabler    ÚinsertÚ
subprocessÚrunÚ
returncodeÚstderrÚstdoutr"   Ú
splitlinesr   r   ÚlistÚglobr`   )r	   rŽ   r�   ÚcmdÚprocÚtailÚwhlsÚtarss           r*   Ú_build_oncer§   ø   s[  € ÝŒ>˜4 ¨)°YØ•s˜6‘{”{¥C¨¡I¤Ið/€Càð (à�
Š
�1Ð&Ñ'Ô'Ð'ÝŒ>˜#¨d¸Ð>Ñ>Ô>€DØ„˜!ÒÐØ”Ð0˜tœ{Ð0¨b×7Ò7Ñ9Ô9×DÒDÑFÔFÀsÀtÀtÔLˆÝØCØ�kŠk˜$ÑÔñ àJñKñ
ô 
ð 	
õ
 �—’˜GÑ$Ô$Ñ%Ô%€DÝ�—’˜JÑ'Ô'Ñ(Ô(€DÝ
ˆ4�y„y�A‚~€~�˜T™œ aš˜ÝÐ[ÀÐ[Ð[ÈdÐ[Ð[ÐUYÐ[Ð[Ñ\Ô\Ð\Ø�Œ7�D˜”GÐÐr=   c                ó  — t          j        | ¦  «        5 }d„ |                     ¦   «         D ¦   «         d         }|                     |¦  «                             dd¦  «        }d d d ¦  «         n# 1 swxY w Y   |                     ¦   «         D ]]}|                     d¦  «        r0|                     dd¦  «        d                              ¦   «         c S |                     ¦   «         s nŒ^t          | j
        › d�¦  «        ‚)	Nc                ó<   — g | ]}|                      d ¦  «        ¯|‘ŒS ©z.dist-info/METADATArV   rX   s     r*   r[   z'_version_from_wheel.<locals>.<listcomp>  ó*   € ÐMÐMÐM�a¨1¯:ª:Ð6KÑ+LÔ+LÐM�ÐMÐMÐMr=   r   rK   r#   zVersion:ú:r   z: METADATA declares no Version)r]   r^   r_   rf   rO   rŸ   re   rr   r"   r   r   )rR   rh   r   ÚmetaÚlines        r*   Ú_version_from_wheelr¯     s0  € Ý	Œ˜Ñ	Ô	ð 7 ØMÐM˜1Ÿ:š:™<œ<ÐMÑMÔMÈaÔPˆØ�vŠv�d‰|Œ|×"Ò" 7¨IÑ6Ô6ˆð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7ð —’Ñ!Ô!ð ð ˆØ�?Š?˜:Ñ&Ô&ð 	1Ø—:’:˜c 1Ñ%Ô% aÔ(×.Ò.Ñ0Ô0Ð0Ð0Ð0Ø�zŠz‰|Œ|ð 	ØˆEð	å
˜œÐ@Ð@Ð@Ñ
AÔ
AÐAó   •AA/Á/A3Á6A3ú	list[str]c                ó  — t          j        | ¦  «        5 }d„ |                     ¦   «         D ¦   «         d         }|                     |¦  «                             dd¦  «        }d d d ¦  «         n# 1 swxY w Y   g }|                     ¦   «         D ]n}|                     ¦   «         s nW|                     d¦  «        rA|                     | 	                    dd¦  «        d                              ¦   «         ¦  «         Œo|S )Nc                ó<   — g | ]}|                      d ¦  «        ¯|‘ŒS rª   rV   rX   s     r*   r[   z"_requires_dist.<locals>.<listcomp>  r«   r=   r   rK   r#   zRequires-Dist:r¬   r   )
r]   r^   r_   rf   rO   rŸ   r"   re   Úappendrr   )rR   rh   r   r­   rg   r®   s         r*   Ú_requires_distrµ     s$  € Ý	Œ˜Ñ	Ô	ð 7 ØMÐM˜1Ÿ:š:™<œ<ÐMÑMÔMÈaÔPˆØ�vŠv�d‰|Œ|×"Ò" 7¨IÑ6Ô6ˆð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7ð €CØ—’Ñ!Ô!ð 6ð 6ˆØ�zŠz‰|Œ|ð 	ØˆEØ�?Š?Ð+Ñ,Ô,ð 	6Ø�JŠJ�t—z’z # qÑ)Ô)¨!Ô,×2Ò2Ñ4Ô4Ñ5Ô5Ð5øØ€Jr°   c                óH  — 	 t          j        | ¦  «        5 }t          j        |                     t
          › d�¦  «                             d¦  «        ¦  «        }ddd¦  «         n# 1 swxY w Y   t          |                     dd¦  «        ¦  «        S # t          $ r Y dS w xY w)zGArchaeology for the ledger entry: which engine this core was sealed to.z
/seal.jsonrK   NÚtagr   )
r]   r^   ÚjsonÚloadsrf   ÚPKG_NAMErO   r    r!   r   )rR   rh   Údatas      r*   Ú_seal_tag_from_wheelr¼   &  sé   € ðÝŒ_˜SÑ!Ô!ð 	O QÝ”:˜aŸfšf­Ð%<Ð%<Ð%<Ñ=Ô=×DÒDÀWÑMÔMÑNÔNˆDð	Oð 	Oð 	Oñ 	Oô 	Oð 	Oð 	Oð 	Oð 	Oð 	Oð 	Oøøøð 	Oð 	Oð 	Oð 	Oå�4—8’8˜E 2Ñ&Ô&Ñ'Ô'Ð'øÝð ð ð Øˆrˆrðøøøs5   ‚B –AA%ÁB Á%A)Á)B Á,A)Á-%B Â
B!Â B!Ú
self_checkÚdictc          	     óô  — t          j        d¬¦  «        5 }t          |¦  «        }t          | |dz  |¦  «        \  }}t	          |¦  «        t          |¦  «        t          |¦  «        dt          |¦  «        idt          |¦  «        i|j	        |j	        dœ}t          |d         d         ¦  «        |d         d<   t          |d         d         ¦  «        |d         d<   |�r t          | |d	z  |¦  «        \  }}	t          |¦  «        t          |	¦  «        }}
t          |
¦  «        |d         d         k    rGt          |d         d         |
¦  «        }t          d
|d         |d         z   |d         z   › d�¦  «        ‚t          |¦  «        |d         d         k    rFt          |d         d         |¦  «        }t          d|d         |d         z   |d         z   › �¦  «        ‚ddd¦  «         n# 1 swxY w Y   |S )zBBuild and describe the artifact. Raises GateBroken, never refuses.zinvisible-core-gate-©ÚprefixÚaÚfiles)ÚversionÚseal_tagÚrequires_distr   rm   Úwheel_filenameÚsdist_filenamer   Údigestrm   r@   zwtwo builds of the SAME tree produced different wheels, so a digest comparison proves nothing here.
  unstable entries: r‰   rŠ   r‹   zW
  pin the build backend, or re-run with --single-build if you accept the weaker check.zKtwo builds of the SAME tree produced different sdists.
  unstable entries: N)ÚtempfileÚTemporaryDirectoryr   r§   r¯   r¼   rµ   rl   rw   r   r‚   r�   r   )r	   r�   r½   ÚtdÚtmprR   rm   rk   Úwhl2Úsdist2Úw2Ús2Úds                r*   ÚinspectrÓ   0  sb  € å	Ô	$Ð,BÐ	CÑ	CÔ	Cð  WÀrÝ�2‰hŒhˆÝ   s¨S¡y°(Ñ;Ô;‰
ˆˆUå*¨3Ñ/Ô/Ý,¨SÑ1Ô1Ý+¨CÑ0Ô0Ø�~¨cÑ2Ô2Ð3Ø�~¨eÑ4Ô4Ð5Ø!œhØ#œjð
ð 
ˆõ #2°$°w´-ÀÔ2HÑ"IÔ"IˆˆWŒ�hÑÝ"1°$°w´-ÀÔ2HÑ"IÔ"IˆˆWŒ�hÑàñ 	Wõ ' t¨S°3©Y¸ÑAÔA‰LˆD�&Ý# DÑ)Ô)­>¸&Ñ+AÔ+A�ˆBÝ˜rÑ"Ô" d¨7¤m°HÔ&=Ò=Ð=Ý" 4¨¤=°Ô#9¸2Ñ>Ô>�Ý ð/à+,¨Y¬<¸!¸G¼*Ñ+DÀqÈÄ|Ñ+Sð/ð /ð /ñ0ô 0ð 0õ ˜rÑ"Ô" d¨7¤m°HÔ&=Ò=Ð=Ý" 4¨¤=°Ô#9¸2Ñ>Ô>�Ý ðVØ+,¨Y¬<¸!¸G¼*Ñ+DÀqÈÄ|Ñ+SðVð VñWô Wð Wð= Wð  Wð  Wñ  Wô  Wð  Wð  Wð  Wð  Wð  Wð  Wøøøð  Wð  Wð  Wð  WðB €Ks   –GG-Ç-G1Ç4G1Úlegrd   ú
str | Nonec                ón  — | dk    r_|                      d¦  «        sdS |dt          d¦  «         …                              d¦  «        }t          |¦  «        dk    r|d         ndS |                      d¦  «        sdS |dt          d¦  «         …         }d|v r|                     dd¦  «        d         ndS )aÒ  The version an artifact filename declares, or None if it declares none.

    A wheel is `<name>-<version>-<python>-<abi>-<platform>.whl` and an sdist is
    `<name>-<version>.tar.gz`, with the distribution name escaped so that it can
    never itself contain a hyphen (PEP 427). So the version is recoverable from
    the name without guessing, and it is a SECOND, independent witness of what
    the entry claims to be - which is the whole point of reading it.
    r   z.whlNr   r-   r   z.tar.gz)rW   r`   rr   ra   )rÔ   rd   ÚpartsÚstems       r*   Ú_version_in_filenamerÙ   X  sÁ   € ð ˆg‚~€~Ø× Ò  Ñ(Ô(ð 	Ø�4Ø˜�3˜v™;œ;˜,˜Ô'×-Ò-¨cÑ2Ô2ˆÝ˜u™:œ:¨š?˜?ˆu�QŒxˆx°Ð4Ø×Ò˜YÑ'Ô'ð ØˆtØÐ$•c˜)‘n”n�_Ð$Ô%€DØ%(¨D [ [ˆ4�;Š;�s˜AÑÔ˜qÔ!Ð!°dÐ:r=   ÚpathÚiÚintÚentryÚobjectÚNonec                ó6  — | › d|› d�}t          |t          ¦  «        s't          |› dt          |¦  «        j        › d�¦  «        ‚|                     d¦  «        }t          |t          ¦  «        r|st          |› d�¦  «        ‚dD �]}|                     |¦  «        }t          |t          ¦  «        st          |› d|› d	|› d
�¦  «        ‚t          |                     d¦  «        t          ¦  «        r|d         st          |› d|› d|› d�¦  «        ‚t          |                     d¦  «        t          ¦  «        r|d         st          |› d|› d|› d�¦  «        ‚d„ |d                              ¦   «         D ¦   «         }|r"t          |› d|› d|› d|dd…         › �¦  «        ‚|› d�}|                     |¦  «        }	t          |	t          ¦  «        r|	st          |› d|› d	|› d�¦  «        ‚t          ||	¦  «        }
|
€t          |› d|› d|› d|	›d|› d�
¦  «        ‚|
|k    rt          |› d|›d|› d|	›d|
›d�
¦  «        ‚t          |d         ¦  «        }||d         k    r7t          |› d|› d|› d|d         dd…         › d|› d |dd…         › d!�¦  «        ‚�ŒdS )"a—  A present-but-malformed entry is GATE BROKEN, never a violation.

    Without this, an entry missing its 'wheel' key blew up inside the diff and
    the caller reported something violation-shaped. The operator then reads
    "the content changed" and starts hunting a change that does not exist, which
    is the exact failure mode that gets gates disabled. Say the record is
    unusable, and say which record.

    Two of the checks below are not shape checks, they are CONSISTENCY checks,
    and both close a measured hole:

      * the version string is the key everything else is looked up by
        (_entry_for matches on it and nothing else), so on its own it is a claim
        with no witness. Editing released[0].version from 18.0.0 to 17.9.0 made
        a drifted 18.0.0 build look like it had never been published and exited
        0 PUBLISH ALLOWED, while every other single-field corruption in this
        file yields exit 2. The recorded filenames carry the version too, so the
        entry can be made to corroborate itself.
      * a digest that does not match the file table it sits next to means the
        entry disagrees with itself, and there is no way to tell which half is
        right. Overwriting both digests with garbage while leaving the tables
        intact used to read as "nothing to release", because the verdict was
        computed from the tables and only the digests were printed.
    z: released[ú]z is z, not an objectrÄ   z has no 'version' string)r   rm   ú (z
) has no 'a  ' record, so there is nothing to compare this build against. The ledger is written only by `version_gate.py record`; a hand edit or a bad merge is the usual cause. Restore it from git history rather than re-recording, or the record of what was actually published is lost.rÃ   z): 'z.files' is missing or emptyrÉ   z.digest' is missingc                óB   — g | ]\  }}t          |t          ¦  «        °|‘ŒS r<   )Ú
isinstancer    )rY   ÚkÚvs      r*   r[   z#_validate_entry.<locals>.<listcomp>˜  s+   € ÐMÐMÐM‘T�Q˜½*ÀQÍÑ:LÔ:LÐMˆqÐMÐMÐMr=   z".files' has non-string hashes for Nr-   Ú	_filenamezÝ'. `record` always writes it, and it is the only thing in the entry that corroborates the version string - without it one edited field turns a published version into an unpublished one. Restore the entry from git history.z' is z, which is not a z. filename this gate can read a version out of.z: the entry says version z
 but its 'z, which was built as a  . The two cannot both be right, so this record cannot say what was published. An edited version string is the usual cause, and on its own it would make a drifted build look like it had never been released. Restore the entry from git history rather than re-recording it.z.digest' is é   z
 but the 'z".files' table beside it hashes to z¶. The entry contradicts itself and there is no way to tell which half is the record of what shipped, so this gate will not compare against either. Restore the entry from git history.)
rä   r¾   r   Útyper8   r!   r    ÚitemsrÙ   r‚   )rÚ   rÛ   rÝ   ÚwhererÄ   rÔ   rH   ÚbadÚkeyrd   ÚdeclaredÚ
recomputeds               r*   Ú_validate_entryrð   l  sD  € ð2 Ð$Ð$ Ð$Ð$Ð$€EÝ�e�TÑ"Ô"ð NÝ˜EÐLÐL¥t¨E¡{¤{Ô';ÐLÐLÐLÑMÔMÐMØ�iŠi˜	Ñ"Ô"€GÝ�g�sÑ#Ô#ð =¨7ð =Ý˜EÐ;Ð;Ð;Ñ<Ô<Ð<Ø!ð /@ñ /@ˆØ�yŠy˜‰~Œ~ˆÝ˜$¥Ñ%Ô%ð 	CÝØð Bð B˜Gð Bð B¨sð Bð Bð BñCô Cð Cõ ˜$Ÿ(š( 7Ñ+Ô+­TÑ2Ô2ð 	X¸$¸w¼-ð 	XÝ ÐVÐV¨ÐVÐV°cÐVÐVÐVÑWÔWÐWÝ˜$Ÿ(š( 8Ñ,Ô,­cÑ2Ô2ð 	P¸$¸x¼.ð 	PÝ ÐNÐN¨ÐNÐN°cÐNÐNÐNÑOÔOÐOØMÐM˜T 'œ]×0Ò0Ñ2Ô2ÐMÑMÔMˆØð 	/Ý ð .ð .¨ð .ð .°cð .ð .Ø$'¨¨¨¤Gð.ð .ñ /ô /ð /ð ÐÐÐˆØ—9’9˜S‘>”>ˆÝ˜(¥CÑ(Ô(ð 	L°ð 	LÝØð Kð K˜Gð Kð K¨sð Kð Kð KñLô Lð Lõ
 (¨¨XÑ6Ô6ˆØÐÝØð Gð G˜Gð Gð G¨ð Gð G°8ð Gð GØðGð Gð GñHô Hð Hð �wÒÐÝØð Gð G°7ð Gð GÈð Gð GØðGð GØ4<ðGð Gð GñHô Hð Hõ % T¨'¤]Ñ3Ô3ˆ
Ø˜˜hœÒ'Ð'ÝØð ?ð ?˜Gð ?ð ?¨ð ?ð ?¸$¸x¼.ÈÈ"ÈÔ:Mð ?ð ?Øð?ð ?Ø;EÀcÀrÀc¼?ð?ð ?ð ?ñ@ô @ð @ñ (ðS/@ð /@r=   c                óÈ  — |                       ¦   «         s"t          | › dt          › d| j        › d�¦  «        ‚	 t	          j        |                      d¬¦  «        ¦  «        }n'# t          $ r}t          | › d|› d�¦  «        ‚d}~ww xY wt          |t          ¦  «        st          | › d	�¦  «        ‚| 
                    d
¦  «        t          k    r/t          | › d| 
                    d
¦  «        ›dt          › �¦  «        ‚t          | 
                    d¦  «        t          ¦  «        st          | › d�¦  «        ‚t          |d         ¦  «        D ]\  }}t          | ||¦  «         Œ|S )aç  Read the ledger, or raise. It NEVER invents one.

    An absent file used to return an empty ledger, and `check` then announced
    "this is release 1" and exited 0. That is the gate's single piece of offline
    memory failing open: a --ledger typo, a deleted file, a shallow checkout or
    a bad merge each disarmed it while a real content change sat in the tree.
    Missing and unreadable are now the same hard stop, and it is a stop the
    operator cannot mistake for a pass.
    a½  : NO LEDGER.
  This file is the gate's only offline memory of what was already
  published. Without it the gate cannot tell a first release from a
  release whose content moved under a version that did not, so it
  refuses to guess.
  Usual causes, in order: a typo in --ledger; a checkout that did not
  bring the repo root; the file deleted or lost in a merge.
  If this really is the first release ever, create it with
    printf '{"schema": z, "released": []}' > "zC"
  and run `check --first-release` - which says so out loud, once.rK   ©Úencodingz: UNREADABLE LEDGER (zµ).
  Restore it from git history. Do not delete it to move on: an absent
  ledger is this same failure, and re-recording would overwrite the
  record of what was actually published.Nz0: UNREADABLE LEDGER (top level is not an object)Úschemaz: ledger schema is z, this gate understands Úreleasedz: ledger has no 'released' list)Úexistsr?   ÚLEDGER_SCHEMAr   r¸   r¹   Ú	read_textr   rä   r¾   r!   r    Ú	enumeraterð   )rÚ   r»   ÚerÛ   rÝ   s        r*   Úload_ledgerrû   ½  sÑ  € ð �;Š;‰=Œ=ð QÝØð 	Pð 	Põ )6ð	Pð 	Pð PTÌyð	Pð 	Pð 	Pñ
Qô 
Qð 
	Qð8ÝŒz˜$Ÿ.š.°'˜.Ñ:Ô:Ñ;Ô;ˆˆøÝð 8ð 8ð 8ÝØð 7ð 7¨!ð 7ð 7ð 7ñ8ô 8ð 	8øøøøð8øøøõ �d�DÑ!Ô!ð [Ý 4Ð YÐ YÐ YÑZÔZÐZØ‡x‚x�ÑÔ�]Ò*Ð*ÝØð ð ¨¯ª°Ñ(:Ô(:ð ð Ýðð ñ ô  ð 	 õ �d—h’h˜zÑ*Ô*­DÑ1Ô1ð JÝ 4Ð HÐ HÐ HÑIÔIÐIÝ˜d :Ô.Ñ/Ô/ð (ð (‰ˆˆ5Ý˜˜a Ñ'Ô'Ð'Ð'Ø€Ks   ¸(A! Á!
BÁ+B Â Br»   c                óÈ   — |                       | j        dz   ¦  «        }|                     t          j        |dd¬¦  «        dz   d¬¦  «         t          j        || ¦  «         d S )Nz.tmpr,   T)ÚindentÚ	sort_keysrz   rK   rò   )Úwith_suffixÚsuffixÚ
write_textr¸   ÚdumpsÚosr#   )rÚ   r»   rÍ   s      r*   Úwrite_ledgerr  è  s`   € Ø
×
Ò
˜4œ;¨Ñ/Ñ
0Ô
0€CØ‡N‚N•4”:˜d¨1¸Ð=Ñ=Ô=ÀÑDÈw€NÑWÔWÐWÝ„Jˆs�DÑÔÐÐÐr=   ÚledgerrÄ   údict | Nonec                óV   — | d         D ]}|                      d¦  «        |k    r|c S Œ d S )Nrõ   rÄ   ©r!   )r  rÄ   rú   s      r*   Ú
_entry_forr	  î  s@   € Ø�JÔð ð ˆØ�5Š5�ÑÔ˜wÒ&Ð&ØˆHˆHˆHð 'àˆ4r=   ræ   útuple[int, int, int] | Nonec                óº   — t                                | ¦  «        }|r>t          |d         ¦  «        t          |d         ¦  «        t          |d         ¦  «        fnd S )Nr   r,   r-   )Ú_VERSION_REÚmatchrÜ   )ræ   Úms     r*   Ú_parse_versionr  õ  sJ   € Ý×Ò˜!ÑÔ€AØ01Ð;�C��!”‰IŒI•s˜1˜Qœ4‘y”y¥# a¨¤d¡)¤)Ð,Ð,°tÐ;r=   ÚlabelrÒ   c           
     óh   — g }dD ],}||         D ]!}|                      d|d›d| › d|› �¦  «         Œ"Œ-|S )Nrˆ   ú    z<8r–   r   )r´   )r  rÒ   ÚlinesÚkindr}   s        r*   Ú_report_diffr  ü  sd   € Ø€EØ/ð 8ð 8ˆØ�4”ð 	8ð 	8ˆAØ�LŠLÐ6 Ð6Ð6Ð6¨%Ð6Ð6°1Ð6Ð6Ñ7Ô7Ð7Ð7ð	8à€Lr=   a  
  Two remedies are legal, and exactly one of them fits:

    1. A core-only fix against the SAME engine
       bump CORE_REVISION in src/invisible_core/_version.py (it is the only
       hand-edited number in the package). {cur} -> {next_rev}
       Never reset it: pip compares with != , not <.

    2. The engine moved
       roll a new seal (a new firefox-N tag in src/invisible_core/seal.json).
       The version follows the tag on its own, no hand edit.

  Then re-run: python scripts/version_gate.py check
aÆ  
  Publishing this as-is is a no-op for every installed copy: pip's
  satisfaction check is name plus version, never content, so nobody
  who already has {cur} would ever receive these bytes.

  Bump `version` in pyproject.toml - {cur} -> {next_rev} - and note the
  change in CHANGELOG.md. Never reuse a version: a PyPI filename can
  never be re-uploaded, so a wrong artifact stays wrong forever.

  Then re-run: python -m invisible_core.release check
c                ó"  — t          | ¦  «        }t          dk    r7|r|d         › d|d         dz   › d�nd}t                               | |¬¦  «        S |r|d         › d|d         › d|d         dz   › �nd	}t                               | |¬¦  «        S )
Nr   r   ú.r   z.0zthe next revision)ÚcurÚnext_revr,   zthe next version)r  rº   ÚREMEDYÚformatÚCONSUMER_REMEDY)rÄ   r}   Únxts      r*   Ú_remedyr  %  s­   € Ý�wÑÔ€AÝÐ#Ò#Ð#Ø()ÐB��1”Ð$Ð$˜˜!œ˜q™Ð$Ð$Ð$Ð$Ð/BˆÝ�}Š} °3ˆ}Ñ7Ô7Ð7Ø)*Ð
BˆQˆqŒTÐ
%Ð
%�A�a”DÐ
%Ð
%˜1˜Qœ4 !™8Ð
%Ð
%Ð
%Ð0B€CÝ×!Ò! g¸Ð!Ñ<Ô<Ð<r=   c                ó˜   — t          | j        ¦  «                             ¦   «         }| j        rt          | j        ¦  «        n	|t          z  S rC   )r   Úproject_rootÚresolver  ÚLEDGER_NAME)Úargsr	   s     r*   Ú_ledger_path_forr$  0  s?   € Ý�Ô!Ñ"Ô"×*Ò*Ñ,Ô,€DØ $¤ÐC�4�”ÑÔÐ°½Ñ1CÐCr=   c                ó2   — t          | dd¦  «        pt          S )zõThe index for THIS project, unless the caller named another.

    Reads the module global, which `main()` rebinds from the resolved
    distribution name. The flag's own default is None on purpose - see the
    comment where it is declared.
    Úindex_json_urlN)ÚgetattrÚDEFAULT_INDEX_JSON_URL)r#  s    r*   Ú_index_url_forr)  5  s   € õ �4Ð)¨4Ñ0Ô0ÐJÕ4JÐJr=   c           
     óª  — t          | j        ¦  «                             ¦   «         }t          | ¦  «        }t	          |¦  «        }	 t          || j        | j         ¬¦  «        }n<# t          $ r/}t          d|› �t          j        ¬¦  «         t          cY d }~S d }~ww xY w|d         }|d         }t          t          › d|› �|rd|› d�nd	z   ¦  «         t          d
|d         d         d d…         › dt          |d         d         ¦  «        › d�¦  «         t          d|d         d         d d…         › dt          |d         d         ¦  «        › d�¦  «         t          d|› dt          |d         ¦  «        › d�¦  «         d„ |d         D ¦   «         }|r<t          d¦  «         |D ]}	t          d|	› �¦  «         Œt          d¦  «         t          S |d         �s<t!          | dd¦  «        s¡t          d¦  «         t          d|› d�¦  «         t          d ¦  «         t          d!¦  «         t          d"¦  «         t          d#¦  «         t          d$¦  «         t          d%¦  «         t          d&¦  «         t          d'¦  «         t          S t          d(¦  «         t          d)¦  «         t          d*¦  «         t          d+¦  «         t          d,¦  «         t#          t%          | ¦  «        ¦  «        }
|
t&          k    r|
S t          d-¦  «         t&          S t!          | dd¦  «        r‰t          d.|› �¦  «         t          d/t          |d         ¦  «        › d0�¦  «         |d         D ]2}t          d|d         › d|                     d1d2¦  «        › d�¦  «         Œ3t          d3¦  «         t          S t+          |¦  «        }|�œt-          d4„ d5„ |d         D ¦   «         D ¦   «         d ¬6¦  «        }|�o||k     rid7                     d8„ |D ¦   «         ¦  «        }t          d9|› d:|› d;�¦  «         t          d<¦  «         t          d=¦  «         t          d>¦  «         t          S t1          ||¦  «        }|€rt          d?|› d@�¦  «         t!          | dAd¦  «        r8t3          |t%          | ¦  «        t          | ¦  «        ¦  «        }
|
t&          k    r|
S t          d-¦  «         t&          S t5          |d         d         |d         d         ¦  «        }t5          |d         d         |d         d         ¦  «        }|d         d         |d         d         k    p|d         d         |d         d         k    }|s‹t          dB|› dC�¦  «         t          dD¦  «         t          dE¦  «         t          dF|                     d1d2¦  «        › �¦  «         t          dG¦  «         t          dH¦  «         t          dI¦  «         t6          S t          dJ¦  «         t          dK|› dL|                     d1dM¦  «        › d�¦  «         t          dN|d         d         d d…         › dO|d         d         d d…         › �¦  «         t          dP|d         d         d d…         › dO|d         d         d d…         › �¦  «         t          dQ¦  «         t9          d|¦  «        t9          d|¦  «        z   D ]}t          |¦  «         Œt          dR¦  «         t          dS¦  «         t          dT                     |¬U¦  «        ¦  «         t          t=          |¦  «        ¦  «         t          S )VN©r�   r½   úGATE BROKEN: ©ÚfilerÄ   rÅ   r–   z  (seal ú)r   ú  wheel r   rÉ   rè   ú  rÃ   z entriesú  sdist rm   z	  ledger z  (rõ   z published)c                óL   — g | ]!}d |                      d¦  «        d         v ¯|‘Œ"S )ú@ú;r   )rr   )rY   Úrs     r*   r[   zcmd_check.<locals>.<listcomp>T  s0   € ÐGÐGÐG�!°°q·w²w¸s±|´|ÀA´Ð0FÐ0FˆAÐ0FÐ0FÐ0Fr=   rÆ   zE
RELEASE REFUSED: a dependency is declared as a direct URL reference.r  a  
  A public index rejects this metadata outright (HTTP 400), and a
  direct reference carries no version specifier, so `pip check` has
  nothing to compare and reports a broken environment as healthy.
  Declare a real specifier instead, for example name==X.Y.Z.Úfirst_releaseFz:
RELEASE REFUSED: the ledger records no published version.z. parses and is empty. That is either the firstzA  release ever, or a ledger that lost its entries - and this gatez@  cannot tell those apart, so it will not guess in the directionz  that lets everything through.z.
  If nothing has ever been published, say so:z8    python scripts/version_gate.py check --first-releasez>  If something HAS been published, restore the ledger from gitzA  history. Do not re-record: `record` would write today's digestszA  as if they were what shipped, and the real record is then gone.zG
FIRST RELEASE DECLARED - the operator states nothing is published yet.z@  The ledger is empty, so there is no earlier content to comparezC  against. This gate starts guarding the moment `record` writes thez>  first entry, and --first-release must never be passed again.zD  Nothing local can check this claim, so the index is asked, always:z
PUBLISH ALLOWEDz2
RELEASE REFUSED: --first-release was passed, but z  already records z published version(s):Úpublished_atzat an unrecorded timez3  The flag exists to be used exactly once. Drop it.c              3  ó   K  — | ]}|®|V — Œ	d S rC   r<   )rY   r}   s     r*   r~   zcmd_check.<locals>.<genexpr>�  s/   è è € ð ð �1Ø�ð Ø���ðð r=   c              3  ó\   K  — | ]'}t          |                     d d¦  «        ¦  «        V — Œ(dS )rÄ   r   N©r  r!   ©rY   rú   s     r*   r~   zcmd_check.<locals>.<genexpr>�  s8   è è € ÐZÐZÀ!�¨¯ª¨i¸Ñ(<Ô(<Ñ=Ô=ÐZÐZÐZÐZÐZÐZr=   )Údefaultr  c              3  ó4   K  — | ]}t          |¦  «        V — Œd S rC   )r    )rY   Úxs     r*   r~   zcmd_check.<locals>.<genexpr>“  s(   è è € Ð1Ð1 Q�#˜a™&œ&Ð1Ð1Ð1Ð1Ð1Ð1r=   z*
RELEASE REFUSED: version went BACKWARDS. z < z, already published.zC  CORE_REVISION was reset, or the seal tag moved down. pip comparesz=  with != , not <, so a version that goes backwards is not anz=  upgrade for anybody and the index will not accept it twice.z	
VERSION z< HAS NEVER BEEN PUBLISHED - it moved since the last release.Úverify_indexz
RELEASE REFUSED: z( is already published and its content iszD  byte-identical to what was published. There is nothing to release,z9  and the index refuses a filename it has already served.z  published z>  (exit 5, not 1: a no-op, not a refusal. A caller that treatsz?   every non-zero alike reports a red release for a tag that isz1   simply pointing at something already shipped.)z>
RELEASE REFUSED: the content changed but the version did not.z  version    z  (published ú?ú  wheel      ú -> ú  sdist      z1
  Files that differ from the published artifact:zC
  Publishing this as-is is a no-op for every installed copy: pip'szC  satisfaction check is name plus version, never content, so nobodyz5  who already has {v} would ever receive these bytes.)ræ   )r   r   r!  r$  rû   rÓ   r�   Úsingle_buildr   Úprintr—   r�   ÚEXIT_BROKENÚ	DIST_NAMEr`   ÚEXIT_REFUSEDr'  Ú_verify_first_releaser)  ÚEXIT_OKr!   r  Úmaxr   r	  Ú_verify_indexr�   ÚEXIT_ALREADY_PUBLISHEDr  r  r  )r#  r	   Úledger_pathr  rk   rú   rÄ   ÚsealÚurlsr6  Úrcr  ÚnewestÚhiÚpriorÚwdiffÚsdiffr‰   r®   s                      r*   Ú	cmd_checkrX  ?  s  € Ý�Ô!Ñ"Ô"×*Ò*Ñ,Ô,€DÝ" 4Ñ(Ô(€KÝ˜Ñ%Ô%€FðÝ�t d¤mÀDÔDUÐ@UÐVÑVÔVˆˆøÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3ÝÐÐÐÐÐÐøøøøðøøøð �9Œo€GØ�
Ô€DÝ	�YÐ
"Ð
"˜Ð
"Ð
"¸DÐ&HÐ&8°Ð&8Ð&8Ð&8Ð&8ÀbÑ
IÑJÔJÐJÝ	Ð
Z�T˜'”] 8Ô,¨S¨b¨SÔ1Ð
ZÐ
ZµS¸¸g¼ÀwÔ9OÑ5PÔ5PÐ
ZÐ
ZÐ
ZÑ[Ô[Ð[Ý	Ð
Z�T˜'”] 8Ô,¨S¨b¨SÔ1Ð
ZÐ
ZµS¸¸g¼ÀwÔ9OÑ5PÔ5PÐ
ZÐ
ZÐ
ZÑ[Ô[Ð[Ý	Ð
J�kÐ
JÐ
J¥c¨&°Ô*<Ñ&=Ô&=Ð
JÐ
JÐ
JÑKÔKÐKð
 HÐG�t˜OÔ,ÐGÑGÔG€DØð ÝÐVÑWÔWÐWØð 	ð 	ˆAÝ�*˜�*�*ÑÔÐÐÝð Mñ 	Nô 	Nð 	Nõ Ðà�*Ôñ "õ �t˜_¨eÑ4Ô4ð 	 ÝÐOÑPÔPÐPÝÐR�{ÐRÐRÐRÑSÔSÐSÝÐUÑVÔVÐVÝÐTÑUÔUÐUÝÐ3Ñ4Ô4Ð4ÝÐCÑDÔDÐDÝÐLÑMÔMÐMÝÐRÑSÔSÐSÝÐUÑVÔVÐVÝÐUÑVÔVÐVÝÐÝÐXÑYÔYÐYÝÐPÑQÔQÐQÝÐSÑTÔTÐTÝÐNÑOÔOÐOÝÐTÑUÔUÐUÝ"¥>°$Ñ#7Ô#7Ñ8Ô8ˆØ•Š=ˆ=ØˆIÝÐ!Ñ"Ô"Ð"Ýˆåˆt�_ eÑ,Ô,ð ÝÐQÀKÐQÐQÑRÔRÐRÝÐR¥3 v¨jÔ'9Ñ#:Ô#:ÐRÐRÐRÑSÔSÐSØ˜
Ô#ð 	]ð 	]ˆAÝÐ[˜˜9œÐ[Ð[¨!¯%ª%°Ð@WÑ*XÔ*XÐ[Ð[Ð[Ñ\Ô\Ð\Ð\ÝÐCÑDÔDÐDÝÐõ ˜Ñ
!Ô
!€CØ
€Ýðð ÐZÐZÀvÈjÔGYÐZÑZÔZð ñ ô Ø(,ð.ñ .ô .ˆð Ð #¨¢, ,Ø—’Ð1Ð1¨&Ð1Ñ1Ô1Ñ1Ô1ˆBÝÐdÀÐdÐdÈBÐdÐdÐdÑeÔeÐeÝÐWÑXÔXÐXÝÐQÑRÔRÐRÝÐQÑRÔRÐRÝÐå�v˜wÑ'Ô'€EØ€}ÝÐ`˜7Ð`Ð`Ð`ÑaÔaÐaÝ�4˜¨Ñ/Ô/ð 	Ý˜w­°tÑ(<Ô(<Õ>NÈtÑ>TÔ>TÑUÔUˆBØ•WŠ}ˆ}Ø�	ÝÐ!Ñ"Ô"Ð"Ýˆõ ˜5 œ>¨'Ô2°D¸´MÀ'Ô4JÑKÔK€EÝ˜5 œ>¨'Ô2°D¸´MÀ'Ô4JÑKÔK€EØ�WŒ~˜hÔ'¨4°¬=¸Ô+BÒBð FØ˜”. Ô*¨d°7¬m¸HÔ.EÒEð ð ð &ÝÐU GÐUÐUÐUÑVÔVÐVÝÐTÑUÔUÐUÝÐIÑJÔJÐJÝÐQ˜UŸYšY ~Ð7NÑOÔOÐQÐQÑRÔRÐRÝÐNÑOÔOÐOÝÐOÑPÔPÐPÝÐAÑBÔBÐBÝ%Ð%å	Ð
KÑLÔLÐLÝ	Ð
Q˜'Ð
QÐ
Q°·	²	¸.È#Ñ0NÔ0NÐ
QÐ
QÐ
QÑRÔRÐRÝ	Ð
[˜% œ.¨Ô2°3°B°3Ô7Ð
[Ð
[¸TÀ'¼]È8Ô=TÐUXÐVXÐUXÔ=YÐ
[Ð
[Ñ\Ô\Ð\Ý	Ð
[˜% œ.¨Ô2°3°B°3Ô7Ð
[Ð
[¸TÀ'¼]È8Ô=TÐUXÐVXÐUXÔ=YÐ
[Ð
[Ñ\Ô\Ð\Ý	Ð
>Ñ?Ô?Ð?Ý˜W eÑ,Ô,­|¸GÀUÑ/KÔ/KÑKð ð ˆÝˆd‰ŒˆˆÝ	Ð
PÑQÔQÐQÝ	Ð
OÑPÔPÐPÝ	Ð
A×
HÒ
HÈ7Ð
HÑ
SÔ
SÑTÔTÐTÝ	�'�'Ñ
Ô
ÑÔÐÝÐó   ÁA$ Á$
BÁ.$BÂBÂBc                ó|  — t          | j        ¦  «                             ¦   «         }t          | ¦  «        }t	          |¦  «        }	 t          || j        | j         ¬¦  «        }n<# t          $ r/}t          d|› �t          j        ¬¦  «         t          cY d }~S d }~ww xY w|d         }t          ||¦  «        }|��é|d         d         |d         d         k    r7|d         d         |d         d         k    rt          |› d�¦  «         t          S t          d	|› d
�t          j        ¬¦  «         t          d|d         d         d d…         › d|d         d         d d…         › �t          j        ¬¦  «         t          d|d         d         d d…         › d|d         d         d d…         › �t          j        ¬¦  «         t          dt!          |d         d         |d         d         ¦  «        ¦  «        t          dt!          |d         d         |d         d         ¦  «        ¦  «        z   D ]}t          |t          j        ¬¦  «         Œt          dt          j        ¬¦  «         t          dt          j        ¬¦  «         t          dt          j        ¬¦  «         t"          S |d                              ||d         t'          j        t*          j        ¦  «                             d¦  «        |d         |d         |d         |d         |d         dœ¦  «         |d                              d„ ¬¦  «         t3          ||¦  «         t          d|› d|› �¦  «         t          d|d         d         › �¦  «         t          d|d         d         › �¦  «         t5          ||t7          | ¦  «        ¦  «         t          S ) Nr+  r,  r-  rÄ   r   rÉ   rm   z: already recorded with these exact digests, nothing to do.z	REFUSED: z1 is already in the ledger with DIFFERENT digests.rB  rè   rC  rD  rÃ   z?  Recording over it would erase the record of what was actuallyzC  published - and it is exactly the drift `check` exists to refuse,z:  made invisible in one command. Bump the version instead.rõ   rÅ   z%Y-%m-%dT%H:%M:%SZrÆ   rÇ   rÈ   )rÄ   rÅ   r8  rÆ   rÇ   rÈ   r   rm   c                óL   — t          |                      dd¦  «        ¦  «        pdS )NrÄ   r   )r   r   r   r;  )rú   s    r*   ú<lambda>zcmd_record.<locals>.<lambda>  s"   € ­.¸¿º¸yÈ"Ñ9MÔ9MÑ*NÔ*NÐ*[ÐR[€ r=   )rí   z	recorded z in r0  r2  )r   r   r!  r$  rû   rÓ   r�   rE  r   rF  r—   r�   rG  r	  rK  r  r�   rI  r´   r   Únowr   ÚutcÚstrftimeÚsortr  Ú_align_changelog_dater)  )	r#  r	   rO  r  rk   rú   rÄ   rU  r®   s	            r*   Ú
cmd_recordrb  Ç  s8  € Ý�Ô!Ñ"Ô"×*Ò*Ñ,Ô,€DÝ" 4Ñ(Ô(€KÝ˜Ñ%Ô%€FðÝ�t d¤mÀDÔDUÐ@UÐVÑVÔVˆˆøÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3ÝÐÐÐÐÐÐøøøøðøøøð �9Œo€GÝ�v˜wÑ'Ô'€EØÑØ�Œ>˜(Ô# t¨G¤}°XÔ'>Ò>Ð>Ø�g”˜xÔ(¨D°¬M¸(Ô,CÒCÐCÝ�WÐXÐXÐXÑYÔYÐYÝˆNÝÐT˜'ÐTÐTÐTÝ”:ð	ñ 	ô 	ð 	åð 0˜e Gœn¨XÔ6°s¸°sÔ;ð 0ð 0Ø�g”˜xÔ(¨¨"¨Ô-ð0ð 0Ý69´jð	Bñ 	Bô 	Bð 	Båð 0˜e Gœn¨XÔ6°s¸°sÔ;ð 0ð 0Ø�g”˜xÔ(¨¨"¨Ô-ð0ð 0Ý69´jð	Bñ 	Bô 	Bð 	Bå! '­>¸%À¼.ÈÔ:QØ:>¸w¼-ÈÔ:Pñ,Rô ,Rñ Sô Så# G­^¸EÀ'¼NÈ7Ô<SØ<@À¼MÈ'Ô<Rñ.Tô .Tñ Uô UñUð 	)ð 	)ˆDõ �$�SœZÐ(Ñ(Ô(Ð(Ð(ÝÐOÝ”:ð	ñ 	ô 	ð 	åÐSÝ”:ð	ñ 	ô 	ð 	åÐJÝ”:ð	ñ 	ô 	ð 	åÐà
ˆ:Ô×ÒØØ˜Ô$Ý œ¥X¤\Ñ2Ô2×;Ò;Ð<PÑQÔQð ˜oÔ.ØÐ/Ô0ØÐ/Ô0Ø�g”Ø�g”ð'ð ñ ô ð ð* ˆ:Ô×ÒÐ [Ð [ÐÑ\Ô\Ð\Ý�˜fÑ%Ô%Ð%Ý	Ð
0�gÐ
0Ð
0 ;Ð
0Ð
0Ñ1Ô1Ð1Ý	Ð
.�T˜'”] 8Ô,Ð
.Ð
.Ñ/Ô/Ð/Ý	Ð
.�T˜'”] 8Ô,Ð
.Ð
.Ñ/Ô/Ð/õ ˜$ ­¸Ñ)=Ô)=Ñ>Ô>Ð>Ý€NrY  c                ó   — t          | j        ¦  «                             ¦   «         }	 t          || j        | j         ¬¦  «        }n<# t          $ r/}t          d|› �t          j	        ¬¦  «         t          cY d }~S d }~ww xY wt          t          j        |d         |d         |d         d         |d         d         t          |d         d	         ¦  «        t          |d         d	         ¦  «        |d
         dœd¬¦  «        ¦  «         t          S )Nr+  r,  r-  rÄ   rÅ   r   rÉ   rm   rÃ   rÆ   )rÄ   rÅ   Úwheel_digestÚsdist_digestÚwheel_entriesÚsdist_entriesrÆ   r,   )rý   )r   r   r!  rÓ   r�   rE  r   rF  r—   r�   rG  r¸   r  r`   rK  )r#  r	   rk   rú   s       r*   Úcmd_showrh    s'  € Ý�Ô!Ñ"Ô"×*Ò*Ñ,Ô,€DðÝ�t d¤mÀDÔDUÐ@UÐVÑVÔVˆˆøÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3ÝÐÐÐÐÐÐøøøøðøøøõ 
�$Œ*Ø˜	”?Ø˜Ô$Ø˜Wœ hÔ/Ø˜Wœ hÔ/Ý˜T 'œ]¨7Ô3Ñ4Ô4Ý˜T 'œ]¨7Ô3Ñ4Ô4Ø˜oÔ.ðð ð ðñ ô ñ ô ð õ €Ns   ¨A Á
A?Á$A:Á4A?Á:A?c           	     óè  — 	 t          | ¦  «        }n1# t          t          f$ r t          dt          j        ¬¦  «         ‚ w xY w|t          k    rt          dt          j        ¬¦  «         |S t          | j        ¦  «         	                    ¦   «         }t          j        d¬¦  «        5 }t          |¦  «        }	 t          ||| j        ¦  «        \  }}nH# t          $ r;}t          d|› �t          j        ¬¦  «         t          cY d}~cddd¦  «         S d}~ww xY wt          j        dd	d
t!          |¦  «        t!          |¦  «        g}| j        rd| j        g|dd…<   | j        rVt          d¦  «         t          dd                     |¦  «        z   ¦  «         t          d¦  «         t          cddd¦  «         S t          dd                     |¦  «        z   ¦  «         t)          j        |¦  «        }	|	j        dk    rRt          d|	j        › d�t          j        ¬¦  «         t          dt          j        ¬¦  «         t          cddd¦  «         S 	 ddd¦  «         n# 1 swxY w Y   t/          | ¦  «        S )aØ  check -> upload -> record, in one command, so the gate cannot be skipped.

    This exists because the first version of this gate was wired to nothing:
    `grep -rn version_gate` over the whole workbench found the script, its test
    and a comment, and an operator running `twine upload dist/*` by hand would
    never have touched it. A gate that depends on somebody remembering it is a
    runbook note wearing a gate's clothes.

    So the upload lives INSIDE the gate rather than beside it. `check` runs
    first, in-process; on anything other than exit 0 this returns that exit code
    unchanged and twine is never reached. The artifacts uploaded are the ones
    the gate just built and digested, from a temporary directory, so there is no
    window in which a stale dist/ gets shipped instead of the thing that was
    checked. `record` runs only after twine returns 0, because the ledger is a
    record of what reached the index and not of what we intended to send.
    z.
upload NOT attempted: the gate could not run.r-  z-
upload NOT attempted: the gate did not pass.zinvisible-core-publish-rÀ   r,  Nr“   ÚtwineÚuploadú--repositoryr.   zB
--dry-run: the gate passed, and this is the upload it authorises:r  r–   z0  Nothing was uploaded and nothing was recorded.z
gate passed, uploading:
    r   z
upload FAILED (twine exit z). Nothing recorded: thezE  ledger records what reached the index, never what we tried to send.)rX  r?   r   rF  r—   r�   rK  r   r   r!  rÊ   rË   r§   r�   rG  r˜   r    Ú
repositoryÚdry_runr   rš   r›   rœ   rb  )
r#  rR  r	   rÌ   rŽ   rR   rm   rú   r¢   r£   s
             r*   Úcmd_publishro     s  € ð"Ý�t‰_Œ_ˆˆøÝ�zÐ*ð ð ð õ 	Ð?ÅcÄjÐQÑQÔQÐQØðøøøð 
�W‚}€}ÝÐ>ÅSÄZÐPÑPÔPÐPØˆ	å�Ô!Ñ"Ô"×*Ò*Ñ,Ô,€DÝ	Ô	$Ð,EÐ	FÑ	FÔ	Fð È"Ý�b‘”ˆð	Ý$ T¨6°4´=ÑAÔA‰JˆC��øÝð 	ð 	ð 	ÝÐ% !Ð%Ð%­C¬JÐ7Ñ7Ô7Ð7ÝÐÐÐÐÐðð ð ð ñ ô ð ð øøøøð	øøøõ Œ~˜t W¨h½¸C¹¼Å#ÀeÁ*Ä*ÐMˆØŒ?ð 	9Ø&¨¬Ð8ˆC��!�‰HØŒ<ð 	ÝÐWÑXÔXÐXÝ�&˜3Ÿ8š8 C™=œ=Ñ(Ñ)Ô)Ð)ÝÐDÑEÔEÐEÝðð ð ð ñ ô ð ð õ 	Ð/°#·(²(¸3±-´-Ñ?Ñ@Ô@Ð@ÝŒ~˜cÑ"Ô"ˆØŒ?˜aÒÐÝÐZ°´ÐZÐZÐZÝ”zð#ñ #ô #ð #åÐYÝ”zð#ñ #ô #ð #åð-ð ð ð ñ ô ð ð ð"  ð#ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð õ. �dÑÔÐsS   ‚ ’.A Â&IÂ7CÃIÃ
DÃ$DÃ?DÄ IÄDÄBIÆ7B	IÉIÉ!IÚurlc                ó‚  — ddl }ddl}	 |j                             | d¬¦  «        5 }t	          j        |                     ¦   «                              d¦  «        ¦  «        }ddd¦  «         n# 1 swxY w Y   nb# |j        j	        $ r-}|j
        dk    ri cY d}~S t          d|› d| › d	�¦  «        ‚d}~wt          $ r}t          d|› d| › d	�¦  «        ‚d}~ww xY wt          |t          ¦  «        r)t          |                     d
i ¦  «        t          ¦  «        st          d| › d�¦  «        ‚|                     d
i ¦  «        S )aB  The index's `releases` map for this distribution: version -> file records.

    THE ONE place this module opens the index. Every reader below is a view of
    this call, so the versions the gate cross-checks and the upload date a
    changelog heading is aligned to cannot come from two fetches that disagree.

    A 404 is an answer, not a failure: the project has never been published.
    Anything else that goes wrong is NOT an answer, and the caller must never be
    able to read it as an empty index - that is the fail-open shape this whole
    file exists to avoid.
    r   Né   )ÚtimeoutrK   i”  zindex cross-check failed: râ   r/  Úreleasesz& did not answer with a releases object)Úurllib.errorÚurllib.requestÚrequestÚurlopenr¸   r¹   rf   rO   ÚerrorÚ	HTTPErrorÚcoder   r   rä   r¾   r!   )rp  Úurllibr6  r»   rú   s        r*   Ú_index_releasesr}  X  s¿  € ð ÐÐÐØÐÐÐðCØŒ^×#Ò# C°Ð#Ñ4Ô4ð 	8¸Ý”:˜aŸfšf™hœhŸošo¨gÑ6Ô6Ñ7Ô7ˆDð	8ð 	8ð 	8ñ 	8ô 	8ð 	8ð 	8ð 	8ð 	8ð 	8ð 	8øøøð 	8ð 	8ð 	8ð 	8øøàŒ<Ô!ð Cð Cð CØŒ6�SŠ=ˆ=ØˆIˆIˆIˆIˆIˆIÝÐA°aÐAÐA¸3ÐAÐAÐAÑBÔBÐBøøøøÝð Cð Cð CÝÐA°aÐAÐA¸3ÐAÐAÐAÑBÔBÐBøøøøðCøøøå�d�DÑ!Ô!ð -­°D·H²H¸ZÈÑ4LÔ4LÍdÑ)SÔ)Sð -Ýð ,°cð ,ð ,ð ,ñ -ô -ð 	-à�8Š8�J Ñ#Ô#Ð#sR   ŠA8 ¦:A,Á A8 Á,A0Á0A8 Á3A0Á4A8 Á8CÂB/ÂCÂB/Â/CÂ<CÃCc                ó:   — t          t          | ¦  «        ¦  «        S )zHEvery version the index serves for this distribution. Raises GateBroken.)r€   r}  )rp  s    r*   Ú_index_versionsr  u  s   € å•/ #Ñ&Ô&Ñ'Ô'Ð'r=   c                ó˜   — t          |¦  «                             | ¦  «        pg }d„ |D ¦   «         }|rt          |¦  «        dd…         ndS )aº  The date the index records for `version`, "YYYY-MM-DD", or None.

    The EARLIEST `upload_time_iso_8601` among that version's files, truncated to
    its date. That is UTC, and it is the same field reduced the same way that the
    consumer's changelog gate compares a heading against
    (`min(f["upload_time_iso_8601"] for f in files)[:10]`). Reading it from here
    rather than from a clock is what makes the two unable to disagree.
    c                ór   — g | ]4}t          |t          ¦  «        ¯|                     d ¦  «        ¯,|d          ‘Œ5S )Úupload_time_iso_8601)rä   r¾   r!   )rY   Úfs     r*   r[   z&_index_upload_date.<locals>.<listcomp>„  sY   € ð Hð Hð H¨AÝ˜A�tÑ$Ô$ðHØ)*¯ªÐ/EÑ)FÔ)FðHˆaÐ&Ô'ð Hð Hð Hr=   Né
   )r}  r!   Úmin)rÄ   rp  rÃ   Ústampss       r*   Ú_index_upload_dater‡  z  se   € õ ˜CÑ Ô ×$Ò$ WÑ-Ô-Ð3°€EðHð H°ð Hñ Hô H€Fà%Ð/�3ˆv‰;Œ;�s˜�sÔÐ¨4Ð/r=   Ú	index_urlc                óÒ  ‡
— | t           z  }|                     ¦   «         sdS 	 t          ||¦  «        Š
n3# t          $ r&}t	          dt           › d|› d�¦  «         Y d}~dS d}~ww xY w‰
€%t	          dt           › dt
          › d|› d�¦  «         dS |                     ¦   «         }|                     d¦  «        }t          j	        d	t          j
        |¦  «        z   d
z   ¦  «        }|                     |¦  «        }|€t	          dt           › d|› d�¦  «         dS |                     d¦  «        ‰
k    r t	          dt           › d|› d‰
› d�¦  «         dS |                     ˆ
fd„|¦  «                             d¦  «        }	t          |	¦  «        t          |¦  «        k    s&J t          |	¦  «        t          |¦  «        f¦   «         ‚|	                     d¦  «        |                     d¦  «        k    sJ ‚|	                     d¦  «        |                     d¦  «        k    sJ ‚|                     |	¦  «         t	          dt           › d|› d|                     d¦  «        › d‰
› d�	¦  «         dS )a•  Give the CHANGELOG heading for `version` the date the index recorded.

    Run straight after the ledger is written, which is the first moment the fact
    EXISTS. Before the upload lands, a heading dated by the person writing it is
    a prediction of a timestamp, and the prediction is wrong whenever the author
    is east of UTC late in the day: 0.16.2 of the wrapper was headed 2026-09-16
    (Rome) against an upload at 2026-09-15T23:21Z, and the consumer's e2e gate
    went red on main. 0.6.0 had been a day out before that, which is why the
    gate's own docstring says dates are compared at all.

    Nothing here invents a date. If the index cannot be reached, or does not
    serve this version yet, the file is left exactly as it is and the reason is
    printed: the consumer's gate is still the net, and a date written
    confidently from the wrong source is worse than a heading nobody touched.
    Nr1  z( NOT aligned: the index did not answer (z&). The heading keeps whatever it says.z' NOT aligned: the index does not serve r–   zM yet, so there is no upload date to copy. The heading keeps whatever it says.rK   z(?m)^(##[ \t]*\[z#\][ \t]*-[ \t]*)(\d{4}-\d{2}-\d{2})z has no `## [z*] - YYYY-MM-DD` heading, nothing to align.r,   z heading for z already reads r  c                ó4   •— |                       d¦  «        ‰z   S )Nr   )Úgroup)r  Úrecordeds    €r*   r\  z'_align_changelog_date.<locals>.<lambda>³  s   ø€  §¢¨¡
¤
¨XÑ 5€ r=   rL   rM   r   rC  z', from the index's upload_time_iso_8601)ÚCHANGELOG_NAMEÚis_filer‡  r   rF  rH  Ú
read_bytesrO   ÚreÚcompileÚescapeÚsearchr‹  Úsubr�   r`   ÚcountÚwrite_bytes)r	   rÄ   rˆ  rÚ   rú   Úrawr•   ÚheadingÚfoundr„   rŒ  s             @r*   ra  ra  ‰  sû  ø€ ð  •.Ñ €DØ�<Š<‰>Œ>ð ØˆðÝ% g¨yÑ9Ô9ˆˆøÝð ð ð Ýð 5•>ð 5ð 5È1ð 5ð 5ð 5ñ 	6ô 	6ð 	6àˆˆˆˆˆøøøøðøøøð ÐÝð 5•>ð 5ð 5Ýð5ð 5Ø$ð5ð 5ð 5ñ 	6ô 	6ð 	6ð 	ˆØ
�/Š/Ñ
Ô
€CØ�:Š:�gÑÔ€DÝŒjÐ,­r¬y¸Ñ/AÔ/AÑAØAñBñ Cô C€Gà�NŠN˜4Ñ Ô €EØ€}Ýð #•>ð #ð #°ð #ð #ð #ñ 	$ô 	$ð 	$àˆØ‡{‚{�1�~„~˜Ò!Ð!ÝÐS•>ÐSÐS°ÐSÐSÈÐSÐSÐSÑTÔTÐTØˆØ
�+Š+Ð5Ð5Ð5Ð5°tÑ
<Ô
<×
CÒ
CÀGÑ
LÔ
L€Cõ ˆs‰8Œ8•s˜3‘x”xÒÐÐ¥# c¡(¤(­C°©H¬HÐ!5ÑÔÐØ�9Š9�WÑÔ §¢¨7Ñ!3Ô!3Ò3Ð3Ð3Ð3Ø�9Š9�UÑÔ˜sŸyšy¨Ñ/Ô/Ò/Ð/Ð/Ð/Ø×Ò�SÑÔÐÝ	ð ?�~ð ?ð ?¨Gð ?ð ?°u·{²{À1±~´~ð ?ð ?Øð?ð ?ð ?ñ @ô @ð @ð @ð @s   £4 ´
A$¾AÁA$úPath | Nonec           
     óp  ‡— 	 t          |¦  «        }n<# t          $ r/}t          d|› �t          j        ¬¦  «         t
          cY d}~S d}~ww xY w| |v r1t          dt          › d| › d�¦  «         t          d¦  «         t          S t          dt          › d| › d	t          |¦  «        › d
�¦  «         	 |�-d„ t          |¦  «         
                    dg ¦  «        D ¦   «         ndŠn# t          $ r dŠY nw xY w‰�»t          ˆfd„|D ¦   «         ¦  «        }|ržt          ¦   «          t          dt          |¦  «        › dt          › d�¦  «         t          dd                     |¦  «        z   ¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          S t          S )zJOptional ONLINE cross-check. The ledger is a claim; the index is the fact.r,  r-  Nz+
RELEASE REFUSED: the index already serves r–   r  z>  A version number can never be reused, not even after a yank.ú  index cross-check: z is not on the index (z versions published)c                ó8   — h | ]}|                      d ¦  «        ’ŒS )rÄ   r  r<  s     r*   ú	<setcomp>z _verify_index.<locals>.<setcomp>Û  s$   € ÐWÐWÐW¨!�Q—U’U˜9Ñ%Ô%ÐWÐWÐWr=   rõ   c              3  ó$   •K  — | ]
}|‰v¯|V — Œd S rC   r<   )rY   ræ   rŒ  s     €r*   r~   z _verify_index.<locals>.<genexpr>à  s-   øè è € Ð@Ð@˜A¨a°xÐ.?Ð.?�aÐ.?Ð.?Ð.?Ð.?Ð@Ð@r=   z"RELEASE REFUSED: the index serves ú version(s) of z! that the ledger does not record:r  ú, zB  Those were published outside this gate, so there is no record ofz?  what shipped under them and a re-release with different byteszA  would go unnoticed. Back-fill them from the artifacts the indexz>  actually serves - not from today's tree, which has moved on.)r  r   rF  r—   r�   rG  rH  rI  r`   rû   r!   r   r€   r   rK  )rÄ   rp  r  Ú	publishedrú   ÚgapsrŒ  s         @r*   rM  rM  Á  s>  ø€ ðÝ# CÑ(Ô(ˆ	ˆ	øÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3ÝÐÐÐÐÐÐøøøøðøøøð �)ÐÐÝÐS½YÐSÐSÈÐSÐSÐSÑTÔTÐTÝÐNÑOÔOÐOÝÐÝ	ð 3¥)ð 3ð 3¨gð 3ð 3Ý�)‰nŒnð3ð 3ð 3ñ 4ô 4ð 4ðàÐ)ð XÐW­{¸6Ñ/BÔ/B×/FÒ/FÀzÐSUÑ/VÔ/VÐWÑWÔWÐWØ/3ð 	ˆøåð ð ð ØˆˆˆðøøøàÐÝÐ@Ð@Ð@Ð@ Ð@Ñ@Ô@Ñ@Ô@ˆØð 		 Ý‰GŒGˆGÝð Bµs¸4±y´yð Bð BÝðBð Bð Bñ Cô Cð Cå�&˜4Ÿ9š9 T™?œ?Ñ*Ñ+Ô+Ð+ÝÐVÑWÔWÐWÝÐSÑTÔTÐTÝÐUÑVÔVÐVÝÐRÑSÔSÐSÝÐÝ€Ns,   ƒ “
A�$AÁAÁAÂ01C" Ã"C1Ã0C1c                ó°  — 	 t          | ¦  «        }nW# t          $ rJ}t          d|› �t          j        ¬¦  «         t          dt          j        ¬¦  «         t
          cY d}~S d}~ww xY w|r¿t          d¦  «         t          dt          |¦  «        › dt          › d�¦  «         t          d	d
                     |dd…         ¦  «        z   t          |¦  «        dk    rdndz   ¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          S t          dt          › d�¦  «         t          d¦  «         t          S )aÜ  The FORCED cross-check behind --first-release. Never optional.

    "Nothing has ever been published" is the one claim in this gate that an
    index can settle outright, and it is also the one claim that turns the gate
    off completely: with an empty ledger there is no earlier content, so a real
    content change sails through. Measured - `check --first-release` on an empty
    ledger and a modified tree exited 0, and `publish --first-release --dry-run`
    went on to print the twine command it authorised. The recipe that gets an
    operator into that state is the printf load_ledger itself prints when the
    ledger is missing, so it is the documented path rather than an exotic one.

    Hence: on that branch the index is asked, always, and it must serve NO
    version at all. An index that cannot be reached is exit 2 (no opinion), not
    exit 0 - which costs nothing real, because release 1 is being run on a
    machine that is about to upload to that same index.
    r,  r-  aX    --first-release forces this cross-check: the claim is that NOTHING
  has been published, and the index is the only thing that can settle
  it. With an empty ledger there is no content to compare against
  either, so passing here would mean the gate checked nothing at all.
  Run it where the index is reachable - the upload needs that anyway.NzG
RELEASE REFUSED: --first-release says nothing has ever been published,z  but the index already serves r   r¬   r  r¡  é   z ...r   zA  So the ledger is empty because it was LOST, not because this iszD  release 1. Restore it from git history. Do not re-record: `record`zC  would write today's digests as if they were what shipped, and thez/  record of what actually shipped is then gone.rœ  z! has no published version, so thez  first-release claim holds.)r  r   rF  r—   r�   rG  r`   rH  r   rI  rK  )rp  r¢  rú   s      r*   rJ  rJ  î  s€  € ð"
Ý# CÑ(Ô(ˆ	ˆ	øÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3Ýð Võ
 ”:ð	ñ 	ô 	ð 	õ ÐÐÐÐÐÐøøøøðøøøð ð ÝÐXÑYÔYÐYÝÐ[µ°I±´Ð[Ð[ÍyÐ[Ð[Ð[Ñ\Ô\Ð\Ýˆf�t—y’y ¨2¨A¨2¤Ñ/Ô/Ñ/½SÀ¹^¼^ÈaÒ=OÐ=O°6°6ÐUWÑXÑYÔYÐYÝÐQÑRÔRÐRÝÐTÑUÔUÐUÝÐSÑTÔTÐTÝÐ?Ñ@Ô@Ð@ÝÐÝ	Ð
N¥)Ð
NÐ
NÐ
NÑOÔOÐOÝ	Ð
(Ñ)Ô)Ð)Ý€Ns   ‚ ’
A&œ?A!ÁA&Á!A&c                  ó   — e Zd ZdZd„ ZdS )Ú_Parseraµ  Argparse exits 2 on a usage error. In this gate 2 means EXIT_BROKEN.

    So `version_gate.py chekc` and "the gate could not reach a verdict" were the
    same number, and a caller reading the exit code could not tell a typo from a
    broken gate. `EXIT_USAGE = 3` had been declared for exactly this and used
    nowhere - open item 5 in `18-gate-inventory.md`, alongside the note that a
    documented code which cannot happen is a false entry in the contract.

    Wired rather than deleted, because the ambiguity is real: `doctor` already
    uses 2 for "a check could not be made", and A3 in that same document warns
    that anything treating 2 as an argparse error will misread it.
    c                ó¼   — |                       t          j        ¦  «         t          j                             | j        › d|› d�¦  «         t          t          ¦  «        ‚)Nz	: error: rz   )Úprint_usager—   r�   ÚwriteÚprogÚ
SystemExitÚ
EXIT_USAGE)ÚselfÚmessages     r*   ry  z_Parser.error&  sO   € Ø×Ò�œÑ$Ô$Ð$ÝŒ
×Ò˜DœIÐ;Ð;°Ð;Ð;Ð;Ñ<Ô<Ð<Ý�Ñ$Ô$Ð$r=   N)r8   r9   r:   r;   ry  r<   r=   r*   r§  r§    s-   € € € € € ðð ð%ð %ð %ð %ð %r=   r§  c                óˆ  — | €!t          t          j        dd …         ¦  «        nt          | ¦  «        } t          dd¬¦  «        }|                     dt          t          ¦  «        d¬¦  «         |                     dd d	t          › d
�¬¦  «         |                     ddd¬¦  «         |                     ddd¬¦  «         |                     d¬¦  «        }d„ }| 	                    dd¬¦  «        } ||¦  «         | 
                    t          ¬¦  «         | 	                    dd¬¦  «        } ||¦  «         |                     dd d¬¦  «         |                     ddd¬¦  «         | 
                    t          ¬¦  «         | 	                    dd¬¦  «        }|                     d d d!¬¦  «         | 
                    t          ¬¦  «         | 	                    d"d#¬¦  «        }| 
                    t          ¬¦  «         |                     | ¦  «        }|j        €|                     | dgz   ¦  «        }	 t#          t%          |j        ¦  «        ¦  «        \  aan<# t,          $ r/}	t/          d$|	› �t          j        ¬%¦  «         t2          cY d }	~	S d }	~	ww xY wt(                               d&d'¦  «        ad(t(          › d)�a	 |                     |¦  «        S # t:          $ r/}
t/          d*|
› �t          j        ¬%¦  «         t<          cY d }
~
S d }
~
wt,          $ r/}
t/          d$|
› �t          j        ¬%¦  «         t2          cY d }
~
S d }
~
ww xY w)+Nr   zversion_gate.pyzIRefuse to publish a core whose content changed but whose version did not.)r«  Údescriptionz--project-rootz<the invisible_core repo root (default: this script's parent)©r=  Úhelpz--ledgerz,path to the ledger (default: <project-root>/r/  z
--isolatedÚ
store_truezAbuild in an isolated env (needs index access; default is offline)©Úactionr³  z--single-buildz/skip the build-twice reproducibility self-checkr¢   )Údestc                ó–   — |                       ddd¬¦  «         |                       ddd¬¦  «         |                       dd d¬	¦  «         d S )
Nz--verify-indexr´  z?also ask the index whether this version already exists (online)rµ  z--first-releasez‹state that nothing has ever been published. Only legal against an empty ledger, only ever once, and always cross-checked against the index.ú--index-json-urlz¨the index JSON API to cross-check against (default: this project's own, derived from its pyproject name). Point it at the index a --repository upload actually lands on.r²  )Úadd_argument)Úsps    r*   Ú_gate_flagszmain.<locals>._gate_flags;  sˆ   € Ø
�ŠÐ(°Ø^ð 	ñ 	`ô 	`ð 	`à
�ŠÐ)°,ð@ð 	ñ 	Aô 	Að 	Að 	�ŠÐ*°DðFð 	ñ 	Gô 	Gð 	Gð 	Gð 	Gr=   Úcheckzthe gate (default))r³  )ÚfnÚpublishzCcheck, then upload, then record - the only supported way to releaserl  z'a twine repository alias, e.g. testpypiz	--dry-runz?run the gate and print the upload it authorises, upload nothingÚrecordz<record this version as published (after a successful upload)r¹  znthe index JSON API to read the upload date from (default: this project's own, derived from its pyproject name)Úshowzprint the digests, no verdictr,  r-  r   r   r0   r1   zNO USABLE LEDGER: )r    r—   Úargvr§  rº  r    ÚDEFAULT_ROOTr"  Úadd_subparsersÚ
add_parserÚset_defaultsrX  ro  rb  rh  Ú
parse_argsr¢   r+   r   r   rH  rº   r   rF  r�   rG  r#   r(  r¾  r?   ÚEXIT_NO_LEDGER)rÂ  r}   r”  r¼  ÚcÚur6  Úsr#  r'   rú   s              r*   ÚmainrÌ  ,  sÍ  € Ø!% �4•”˜˜˜”ÑÔÐµ4¸±:´:€DÝØØ_ð	añ 	aô 	a€Að ‡N‚NÐ#­SµÑ->Ô->ØVð ñ Xô Xð Xà‡N‚N�: tØUÅ{ÐUÐUÐUð ñ Wô Wð Wà‡N‚N�<¨Ø[ð ñ ]ô ]ð ]à‡N‚NÐ#¨LØIð ñ Kô Kð Kà
×
Ò
 Ð
Ñ
&Ô
&€CðGð Gð Gð0 	�Š�wÐ%9ˆÑ:Ô:€AØ€K��N„N€NØ‡N‚N•i€NÑ Ô Ð Ø�Š�yð (Bˆñ 	Cô 	C€Aà€K��N„N€NØ‡N‚N�>¨4Ð6_€NÑ`Ô`Ð`Ø‡N‚N�; |ØYð ñ [ô [ð [à‡N‚N•k€NÑ"Ô"Ð"Ø�Š�xÐ&dˆÑeÔe€Að
 ‡N‚NÐ%¨tð*ð ñ +ô +ð +ð ‡N‚N•j€NÑ!Ô!Ð!Ø�Š�vÐ$CˆÑDÔD€AØ‡N‚N•h€NÑÔÐØ�<Š<˜ÑÔ€DØ„xÐà�|Š|˜D G 9Ñ,Ñ-Ô-ˆðÝ6µt¸DÔ<MÑ7NÔ7NÑOÔOÑˆ	�8�8øÝð ð ð ÝÐ#˜cÐ#Ð#­#¬*Ð5Ñ5Ô5Ð5ÝÐÐÐÐÐÐøøøøðøøøõ ×!Ò! # sÑ+Ô+€IØFµiÐFÐFÐFÐð
Ø�wŠw�t‰}Œ}ÐøÝð ð ð õ 	Ð& 1Ð&Ð&­S¬ZÐ8Ñ8Ô8Ð8ÝÐÐÐÐÐÐøøøøÝð ð ð ÝÐ!˜aÐ!Ð!­¬
Ð3Ñ3Ô3Ð3ÝÐÐÐÐÐÐøøøøðøøøsN   È4$I É
JÉ#$JÊJÊJÊ<K Ë
MË$LË?MÌMÌ$L<Ì6MÌ<MÚ__main__)r	   r
   r   r   )r@   rA   r   r    )rH   rA   r   rA   )rR   r   r   rS   )rm   r   r   rS   )rx   rS   r   r    )rƒ   rS   r„   rS   r   r…   )r	   r   rŽ   r   r�   r�   r   r‘   )rR   r   r   r    )rR   r   r   r±   )r	   r   r�   r�   r½   r�   r   r¾   )rÔ   r    rd   r    r   rÕ   )rÚ   r   rÛ   rÜ   rÝ   rÞ   r   rß   )rÚ   r   r   r¾   )rÚ   r   r»   r¾   r   rß   )r  r¾   rÄ   r    r   r  )ræ   r    r   r
  )r  r    rÒ   r…   r   r±   )rÄ   r    r   r    )r   r   )r   r    )r   rÜ   )rp  r    r   r¾   )rp  r    r   r±   )rÄ   r    rp  r    r   rÕ   )r	   r   rÄ   r    rˆ  r    r   rß   rC   )rÄ   r    rp  r    r  rš  r   rÜ   )rp  r    r   rÜ   )Qr;   Ú
__future__r   ÚargparserD   r¸   r  r�  rš   r—   ro   rÊ   r]   r   r   Úpathlibr   Ú__file__r!  ÚparentÚ
SCRIPT_DIRÚcwdrÃ  r"  r÷   r�  rH  rº   r+   rK  rI  rG  r­  rÈ  rN  r(  r‘  r  Ú	frozensetrs   r   r   r?   rG   rQ   rl   rw   r‚   r�   r§   r¯   rµ   r¼   rÓ   rÙ   rð   rû   r  r	  r  r  r  r  r  r$  r)  rX  rb  rh  ro  r}  r  r‡  ra  rM  rJ  ÚArgumentParserr§  rÌ  r8   Úexitr<   r=   r*   ú<module>rØ     så  ððð ð. #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø €€€Ø 	€	€	€	Ø 	€	€	€	Ø Ð Ð Ð Ø 
€
€
€
Ø €€€Ø €€€Ø €€€Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø Ð Ð Ð Ð Ð àˆT�(‰^Œ^×#Ò#Ñ%Ô%Ô,€
ð ˆtŒx‰zŒz€Ø€Ø€ð  €ð €	Ø€ðð ð ð ð, BOÑ >€ˆ�{ J°ð Ð ð Cµ)ÐBÐBÐBÐ àˆbŒjÐ1Ñ2Ô2€ð �9ÐUÐUÐUÑVÔVÐ ð?ð ?ð ?ð ?ð ?�ñ ?ô ?ð ?ðUð Uð Uð Uð U˜	ñ Uô Uð Uð)ð )ð )ð )ð.>ð .>ð .>ð .>ðbð ð ð ð<ð ð ð ð&/ð /ð /ð /ð
ð ð ð ðð ð ð ð*	Bð 	Bð 	Bð 	Bð
ð 
ð 
ð 
ðð ð ð ð#ð #ð #ð #ðP;ð ;ð ;ð ;ð(N@ð N@ð N@ð N@ðb(ð (ð (ð (ðVð ð ð ðð ð ð ð<ð <ð <ð <ðð ð ð ð
€ð(
€ð=ð =ð =ð =ðDð Dð Dð Dð
Kð Kð Kð KðEð Eð Eð EðPCð Cð Cð CðLð ð ð ð&5ð 5ð 5ð 5ðp$ð $ð $ð $ð:(ð (ð (ð (ð
0ð 0ð 0ð 0ð5@ð 5@ð 5@ð 5@ðp*ð *ð *ð *ð *ðZ'ð 'ð 'ð 'ðT%ð %ð %ð %ð %ˆhÔ%ñ %ô %ð %ð(\ð \ð \ð \ð \ð~ ˆzÒÐØ€C„HˆTˆT‰VŒVÑÔÐÐÐð Ðr=   