+
    jHàjO ã            
      ó,  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIHtHt ^ RIHtHtHt ^ RIHt ^ RIHtHt ]P2                  ! ]4      t^t/ tR]R&   R	t]P@                  ! R
RR7      t!R]R&   ]P@                  ! RRR7      t"R]R&   ]R 4       t#R R lt$R R lt%R R lt&R R lt'R R R llt(RR/R R llt)R  R! lt* ! R" R#4      t+R$ R% lt,R& R' lt-R( R) lt.R* R+ lt/R, R- lt0R. R/ lt1R0 R1 lt2R2 R3 lt3R4RR5R/R6 R7 llt4R8 R9 lt5]6! 0 R¡m4      t7]6! 0 R¢m4      t8R: R; lt9R<R=/R> R? llt:R@ RA lt;RB RC lt<RD RE lt=RF RG lt>R£RH RI llt?RJ RK lt@RL RM ltARN RO ltBRP RQ ltCRR RS ltD]	PŠ                  ! RT4      tFRU RV ltGR¤RW RX lltHRY RZ ltIR[ R\ ltJR¥R] R^ lltKR_ R` ltL]	PŠ                  ! Ra4      tM]	PŠ                  ! Rb4      tNRc Rd ltORe Rf ltPRg Rh ltQRi Rj ltRRk Rl ltSRm Rn ltTR¥Ro Rp lltURq Rr ltVRs^‚/Rt Ru lltWRv Rw ltXRx Ry ltYRz R{ ltZR| R} lt[R~ R lt\R€ R� lt]^t^R‚ Rƒ lt_R„ R… lt`R† R‡ ltaRˆtbR‰tcRŠ R‹ ltdR¦RŒ R� llteRŽR�0tfR�RR‘R/R’ R“ lltgR”R•R–R—R˜R™RˆRš]cR›/thRœtiR�tjRž RŸ ltkR# )§uõ  Structured update receipts + post-update fleet version verification.

Phase 1 of the fleet-update reliability plan (#91277): the updater must
*prove* its outcome instead of assuming it.

Two additive capabilities, both designed so a failure inside them can never
break an update (every public entry point is exception-swallowing):

1. **Update receipt** â€” a machine-readable JSON record of what one
   ``hermes update`` run discovered, did, skipped (and why), written to
   the ROOT home's ``logs/update_receipts/`` (``get_default_hermes_root()``,
   never a sticky profile's ``HERMES_HOME``). Silent-failure classes this
   makes visible: #88848 (helper died after "success" printed), #74973
   (restart silently skipped), #85753 (restart phase never ran), #81193
   (desktop shows failure for a successful update).

2. **Fleet version verification** â€” after the restart phase, read every
   profile's ``gateway_state.json``, compare each live gateway's stamped
   ``code_sha`` (written by ``gateway/status.py`` on every runtime-status
   write) against the freshly-updated checkout's HEAD, and print a fleet
   version matrix. Mixed-version fleets (#88654, #69754, #77553, #56717)
   become a loud, actionable report instead of a latent state.

Deployment-kind awareness (docker/image-managed installs) rides on
``hermes_cli.version_info.get_code_identity()``: a packaged build reports
its install-stamp provenance (``source="docker"``/``"nix"``/â€¦) and the
receipt records that the install is not in-place updatable.
)ÚannotationsN)ÚcontextmanagerÚsuppress)ÚdatetimeÚtimezoneÚUTC)ÚPath)ÚAnyÚOptionalzdict[str, dict[str, Any]]Ú
_FINALIZEDzcompleted at command boundaryÚupdate_receipt_current©Údefaultz/contextvars.ContextVar[Optional[UpdateReceipt]]Ú_currentÚupdate_receipt_scope_terminalz0contextvars.ContextVar[Optional[dict[str, Any]]]Ú_scope_terminalc               #  ó  "  € \         P                  R4      p \        P                  / 4      p Rx € \        P                  V4       \         P                  V 4       R#   \        P                  T4       \         P                  T 4       i ; i5i)zDKeep the command's finalization guard away from an enclosing update.N)r   Úsetr   Úreset)ÚtokenÚterminals     Ú>/home/ubuntu/.hermes/hermes-agent/hermes_cli/update_receipt.pyÚupdate_receipt_scoper   E   sd   é € ô �L‰L˜Ó€EÜ×"Ñ" 2Ó&€HðÛä×Ñ˜hÔ'Ü�‰�uÖøô 	×Ñ˜hÔ'Ü�‰�uÕüs   ‚+B®A ²,BÁ,B
Â
Bc               ó    € V ^8„  d   QhRRRR/# )é   Údatar	   ÚreturnÚNone© )Úformats   "r   Ú__annotate__r    Q   s   € ÷ .ñ . ð .¨ñ .ó    c                óÄ   € \         P                  4       pVeH   \        V \        4      '       d0   V P                  R4      '       d   V P                  R4      VR&   R# R# R# R# )zZA completion child finalized this command's run: its terminal outcome is this scope's too.NÚfinished_atÚoutcome)r   ÚgetÚ
isinstanceÚdict)r   Úcells   & r   Úadopt_terminal_receiptr)   Q   sN   € ä×ÑÓ €DØÒœJ t¬T×2Ò2°t·x±xÀ×7NÒ7NØŸ(™( 9Ó-ˆˆY‹ñ 8OÑ2Ñr!   c               ó   € V ^8„  d   QhRR/# ©r   r   Úboolr   )r   s   "r   r    r    X   s   € ÷ Vñ V˜4ñ Vr!   c                 ó´   € \         P                  4       p \        P                  4       RJ ;'       d(    \        V 4      ;'       d    V P                  R4      R8H  # )a  True when this command's run is closed and its receipt says ``success`` (C3).

The gateway ``/update`` status written at the command boundary follows the receipt: an
interrupt or error that escapes after the run closed as a success never reports it failed.
Nr$   Úsuccess)r   r%   r   r,   )r(   s    r   Úcommitted_successr/   X   sE   € ô ×ÑÓ €DÜ�<‰<‹>˜TÐ!×UÐU¤d¨4£j×UÐU°T·X±X¸iÓ5HÈIÑ5UÐUr!   c               ó   € V ^8„  d   QhRR/# ©r   r   úOptional[str]r   )r   s   "r   r    r    b   s   € ÷ 	Cñ 	C ñ 	Cr!   c                 óN   € \         P                  4       p V e   V P                  # R# )u†  The update correlation id in force in this context, or None.

Derived from the OPEN update receipt itself â€” one source of truth, no
duplicate id variable: a nested update's begin replaces the current
receipt (so syncs begun under it capture the nested id), and its
finalize RESTORES the outer receipt via the ContextVar token (so the
outer id comes back for the rest of the outer update).N)r   r%   Úcorrelation_id©Úcurrents    r   Úcurrent_correlation_idr7   b   s%   € ô �l‰l‹n€GØ%,Ò%8ˆ7×!Ñ!ÐB¸dÐBr!   c               ó   € V ^8„  d   QhRR/# )r   r   Ústrr   )r   s   "r   r    r    n   s   € ÷ )ñ )�cñ )r!   c                 óR   € \         P                  ! \        4      P                  4       # ©N)r   Únowr   Ú	isoformatr   r!   r   Ú_utc_now_isor>   n   s   € Ü�<Š<œÓ×&Ñ&Ó(Ð(r!   Fc               ó    € V ^8„  d   QhRRRR/# )r   Úrefreshr,   r   údict[str, Any]r   )r   s   "r   r    r    r   s   € ÷ ñ ˜Dð ¨^ñ r!   c                ó    € \        \        4      ;_uu_ 4        ^ RIHp V! V R7      ;'       g    / uuRRR4       #   + '       g   i     / # ; i)z6Running-code identity, or ``{}`` when the probe fails.)Úget_code_identity©r@   N)r   Ú	ExceptionÚhermes_cli.version_inforC   )r@   rC   s   & r   Ú_code_identityrG   r   s6   € ä	”)×	Õ	Ý=á ¨Ô1×7Ð7°R÷ 
×	×	Ñ	ð €Iús	   ˜<¼A	Úpidc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úentriesr	   Úkeysztuple[str, ...]rH   r,   r   úlist[dict[str, Any]]r   )r   s   "r   r    r    {   s)   € ÷ 	ñ 	˜#ð 	 _ð 	¸dð 	ÐOcñ 	r!   c               óN  € . pV  F—  p\        V\        4      '       g   K  V'       d(   R\        VP                  R^ 4      ;'       g    ^ 4      /M/ pTP	                  V Uu/ uF  qf\        VP                  VR4      4      bK   	  up4       VP                  V4       K™  	  V# u upi )zXDict entries reduced to stringified ``keys`` (plus an int ``pid`` first when requested).rH   Ú )r&   r'   Úintr%   Úupdater9   Úappend)rJ   rK   rH   ÚrecordsÚentryÚrecordÚkeys   &&$    r   Ú_str_recordsrV   {   s�   € à€GÛˆÜ˜%¤×&Ò&ÙßKN %¬¨U¯Y©Y°u¸aÓ-@×-EÐ-EÀAÓ)FÑ!GÐTVˆØ�‰¹tÓD¹t¸œC §	¡	¨#¨rÓ 2Ó3Ò3¹tÑDÔEØ�‰�vÖñ ð €Nùò Es   Á $B"
c               ó   € V ^8„  d   QhRR/# r1   r   )r   s   "r   r    r    ‡   s   € ÷ Nñ N -ñ Nr!   c                 ór   € \         P                  P                  RR4      P                  4       ;'       g    R# )a  Correlation id handed in by an external launcher, or None.

Desktop's managed SSH update exports ``HERMES_UPDATE_CORRELATION_ID`` and
only accepts a receipt whose ``correlation_id`` equals it. This is separate
from ``update_id``, which stays the CLI's own id for pm sync receipts.ÚHERMES_UPDATE_CORRELATION_IDrN   N)ÚosÚenvironr%   Ústripr   r!   r   Ú_launcher_correlation_idr]   ‡   s+   € ô �:‰:�>‰>Ð8¸"Ó=×CÑCÓE×MÐMÈÐMr!   c                  ó¢   € ] tR t^�tRtR R ltRR R lltR R ltR	 R
 ltR R lt	R R lt
RRRRRRRRRRRRRRRR/R R lltR R ltRtR# )ÚUpdateReceiptz;Collects the observable facts of one ``hermes update`` run.c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r    ÚUpdateReceipt.__annotate__“   s   € ÷ Xñ X˜$ñ Xr!   c                	óê  € R ^R\        4       RRR\        \        P                  4      R\        P
                  ! 4       RRR\        4       R	/ R
. R. R/ R. /V n        \        P                  ! 4       P                  V n        V P                  V P                  R&   \        4       V P                  R&   \        P                  P                  RR4      P                  4       ;'       g    RV P                  R&   R# )ÚschemaÚ
started_atr#   NÚargvrH   r$   ÚrunningÚ
pre_updateÚpost_updateÚstepsÚskipsÚgateway_restartÚfleetÚ	update_idr4   ÚHERMES_ACTION_IDrN   Ú	action_id)r>   ÚlistÚsysrf   rZ   ÚgetpidrG   r   ÚuuidÚuuid4Úhexr4   r]   r[   r%   r\   )Úselfs   &r   Ú__init__ÚUpdateReceipt.__init__“   sÂ   € à�a˜¤|£~°}ÀdØ”DœŸ™“N E¬2¯9ª9«;Ø�yØœ.Ó*¨M¸2Ø�R˜ "Ð&7¸¸WÀbð%
ˆŒ	ô #Ÿjšj›l×.Ñ.ˆÔØ!%×!4Ñ!4ˆ�	‰	�+ÑÜ&>Ó&@ˆ�	‰	Ð"Ñ#ô "$§¡§¡Ð0BÀBÓ!G×!MÑ!MÓ!O×!WÐ!WÐSWˆ�	‰	�+Ór!   rN   c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r   Únamer9   Úokr,   Údetailr   r   r   )r   s   "r   r    rb   ¤   s.   € ÷ jñ j˜ð j $ð j°ð j¸Tñ jr!   c                	ó|   € V P                   R ,          P                  RVR\        V4      RVR\        4       /4       R# )rj   r|   r}   r~   ÚatN)r   rQ   r,   r>   )rw   r|   r}   r~   s   &&&&r   ÚstepÚUpdateReceipt.step¤   s3   € Ø�	‰	�'Õ×!Ñ! 6¨4°´t¸B³xÀÈ6ÐSWÔYeÓYgÐ"hÖir!   c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r|   r9   Úreasonr   r   r   )r   s   "r   r    rb   §   s&   € ÷ Zñ Z˜ð Z cð Z¨dñ Zr!   c           	     	óf   € V P                   R ,          P                  RVRVR\        4       /4       R# )rk   r|   r…   r€   N)r   rQ   r>   )rw   r|   r…   s   &&&r   ÚskipÚUpdateReceipt.skip§   s(   € Ø�	‰	�'Õ×!Ñ! 6¨4°¸6À4ÌËÐ"XÖYr!   c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r   r|   r9   r$   Úfactsr   r   r   )r   s   "r   r    rb   ª   s.   € ÷ uñ u˜#ð u¨ð u°cð u¸dñ ur!   c           	     	ó|   € V P                   P                  R . 4      P                  RVRVR\        4       /VC4       R# )Ústagesr|   r$   r€   N©r   Ú
setdefaultrQ   r>   )rw   r|   r$   r‹   s   &&&,r   ÚstageÚUpdateReceipt.stageª   s9   € à�	‰	×Ñ˜X rÓ*×1Ñ1°6¸4ÀÈGÐUYÔ[gÓ[iÐ2sÐmrÐ2sÖtr!   c               ó$   € V ^8„  d   QhRRRRRR/# ©r   rU   r9   Úvaluer	   r   r   r   )r   s   "r   r    rb   ®   s!   € ÷ ñ ˜ð  Cð ¨Dñ r!   c                	ó"   € W P                   V&   R # r;   )r   )rw   rU   r”   s   &&&r   ÚfactÚUpdateReceipt.fact®   s   € Ø�	‰	�#‹r!   c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r�   r9   r…   r   r   r   )r   s   "r   r    rb   ±   s&   € ÷ mñ m˜Sð m¨#ð m°$ñ mr!   c           	     	óx   € V P                   P                  R . 4      P                  RVRVR\        4       /4       R# )Ú	followupsr�   r…   r€   NrŽ   )rw   r�   r…   s   &&&r   ÚfollowupÚUpdateReceipt.followup±   s3   € Ø�	‰	×Ñ˜[¨"Ó-×4Ñ4°f¸dÀHÈfÐVZÔ\hÓ\jÐ5kÖlr!   Úrestarted_servicesNÚrelaunched_profilesÚexternally_supervised_profilesÚkilled_pidsÚfailed_unitsÚ
incompleteFÚphase_errorÚfresh_recoveryc               ó<   € V ^8„  d   QhRRRRRRRRRRRRR	R
RRRR/	# )r   rž   úlist | NonerŸ   r    r¡   r¢   r£   r,   r¤   r9   r¥   zdict[str, Any] | Noner   r   r   )r   s   "r   r    rb   ´   s`   € ÷ '.ñ '.Ø%0ð'.ØNYð'.à(3ð'.àITð'.ð "ð'.ð 7;ð'.ð RUð'.ð .ð	'.ð
 
ñ'.r!   c               	ób  € R \        T;'       g    . 4      R\        T;'       g    . 4      R\        T;'       g    . 4      RT;'       g    .  U	u. uF  p	\        V	4      NK  	  up	RT;'       g    .  U
u. uF  p
\        V
4      NK  	  up
R\        V4      RV/pVeå   R UUu/ uF.  pYÈP	                  V. 4       Uu. uF  p\        V4      NK  	  upbK0  	  ppp\        VP	                  R. 4      R4      VR&   VP	                  R	4      ;'       g    / pR UUu/ uF7  qÌVP	                  V4      ;'       g    .  Uu. uF  p\        V4      NK  	  upbK9  	  uppVR	&   \        VP	                  R
. 4      RRR7      VR
&   WëR&   W°P                  R&   R# u up	i u up
i u upi u uppi u upi u uppi )rž   rŸ   r    r¡   r¢   r£   r¤   NÚskippedÚserve_unitsÚstale_runtimesT)rH   r¥   rl   )Ú	requestedÚverifiedÚrelaunch_attemptedÚfailed)ÚprofileÚkindÚ
supervisorr…   )r­   r¯   )r±   r°   r²   )rq   rO   r9   r,   r%   rV   r   )rw   rž   rŸ   r    r¡   r¢   r£   r¤   r¥   ÚpÚuÚresultrU   r°   Ú	persistedrª   Úunits   &$$$$$$$$        r   Úgateway_restart_resultÚ$UpdateReceipt.gateway_restart_result´   s×  € ð !¤$Ð'9×'?Ð'?¸RÓ"@Ø!¤4Ð(;×(AÐ(A¸rÓ#BØ,¬dÐ3Q×3WÐ3WÐUWÓ.XØ¨[×->Ð->¸BÐ->Ó@Ñ-> qœC žFÑ->Ñ@Ø¨l×.@Ð.@¸bÐ.@ÓBÑ.@¨œS žVÑ.@ÑBØœ$˜zÓ*Ø˜;ð"
ˆð Ò%ñ Uô)áT�Cð ×2DÑ2DÀSÈ"Ô2MÓNÑ2M w”c˜'–lÑ2MÑNÒNÙTð ñ )ô $0Ø×"Ñ" 9¨bÓ1Ð3^ó$ˆI�iÑ ð )×,Ñ,¨]Ó;×AÐA¸rˆKáUkô(ÙUkÈc¨[¯_©_¸SÓ-A×-GÐ-GÀRÐ-GÓIÑ-G D”c˜$–iÑ-GÑIÒIÑUkò(ˆI�mÑ$ô +7Ø×"Ñ"Ð#3°RÓ8Ð:[Ðaeô+ˆIÐ&Ñ'ð (1Ð#Ñ$Ø'-�	‰	Ð#Ó$ùò; AùÚBùò Oùó)ùò Jùó(sB   ÁFÁ4FÂ"F Â;FÃF ÄF+Ä5F+Ä:F&ÅF+ÆF Æ&F+c               ó    € V ^8„  d   QhRRRR/# )r   r$   r9   r   r   r   )r   s   "r   r    rb   Ý   s   € ÷ @ñ @ ð @¨ñ @r!   c                	óÖ   € VR 8X  d$   V P                   P                  R4      '       d   RpWP                   R&   \        4       V P                   R&   \        RR7      V P                   R&   R# )	r.   Úuser_actionÚpartialr$   r#   TrD   ri   N)r   r%   r>   rG   )rw   r$   s   &&r   ÚfinalizeÚUpdateReceipt.finalizeÝ   sP   € Ø�iÔ D§I¡I§M¡M°-×$@Ò$@ØˆGØ&�	‰	�)ÑÜ#/£>ˆ�	‰	�-Ñ Ü#1¸$Ô#?ˆ�	‰	�-Ó r!   )r4   r   ©rN   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rx   r�   r‡   r�   r–   rœ   r¸   r¾   Ú__static_attributes__r   r!   r   r_   r_   �   s…   † ÙEõX÷"jõZõuõõmð'.Ø37ð'.Ø\`ð'.à6:ð'.àW[ð'.ð %)ð'.ð >Cð'.ð XZð'.ð 15÷	'.÷R@ñ @r!   r_   c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r    r    å   s   € ÷ Bñ B�dñ Br!   c                 ó8   € ^ RI Hp  V ! 4       R,          R,          # )é    ©Úget_default_hermes_rootÚlogsÚupdate_receipts)Úhermes_constantsrË   rÊ   s    r   Ú_receipt_dirrÏ   å   s   € õ
 9á"Ó$ vÕ-Ð0AÕAÐAr!   c               ó   € V ^8„  d   QhRR/# )r   r   z
list[Path]r   )r   s   "r   r    r    ï   s   € ÷ Nñ N�zñ Nr!   c                 óœ   € ^ RI Hp  \        4       V ! 4       R,          R,          r!VP                  4       VP                  4       8X  d   V.# W.# )a5  The root store, then the profile's own when a named profile makes them differ. ``pm/``
writes its sync receipts to ``get_hermes_home()`` and receipts from before the root move live
there too, so readers take both and writers mirror ``latest.json`` into it (``hermes -p <name>
pm status`` reads only that one).©Úget_hermes_homerÌ   rÍ   )rÎ   rÓ   rÏ   Úresolve)rÓ   Úrootr°   s      r   Ú_receipt_dirsrÖ   ï   sA   € õ
 1ä “N¡OÓ$5¸Õ$>ÐARÕ$Rˆ'Ø—_‘_Ó&¨$¯,©,«.Ô8ˆDˆ6ÐM¸t¸oÐMr!   c               ó    € V ^8„  d   QhRRRR/# )r   ÚpayloadÚbytesr   r   r   )r   s   "r   r    r    ú   s   € ÷ :ñ :˜5ð : Tñ :r!   c                óz   € ^ RI Hp \        4        F&  pVP                  RRR7       V! VR,          V 4       K(  	  R# )zFReplace ``latest.json`` in every store a reader of this home consults.©Ú_atomic_bytesT©ÚparentsÚexist_okúlatest.jsonN)Úhermes_cli.runtime_staterÜ   rÖ   Úmkdir)rØ   rÜ   Ú	directorys   &  r   Ú_write_latesträ   ú   s0   € å6ä"–_ˆ	Ø�‰ ¨tˆÔ4Ù�i -Õ/°Ö9ó %r!   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rã   r   r   rA   r   r   )r   s   "r   r    r      s&   € ÷ wñ w˜ð w ^ð w¸ñ wr!   c                ó~  € \         P                  ! RR\        VP                  R4      ;'       g    R4      4      R,          ;'       g    \        P
                  ! R4      pT RVR,           RVR	,           RVP                  R
4      ;'       g    \        P                  ! 4        RVP                  R4       R2	,          # )zVOne archive file per run, named at begin so the running and terminal records coincide.z[^0-9]rN   re   :Né   Nz%Y%m%d%H%M%SÚupdate_ºNé   NÚ_:rê   NNrH   rn   ú.json)ÚreÚsubr9   r%   ÚtimeÚstrftimerZ   rs   )rã   r   Ústamps   && r   Ú	_run_filerò     s–   € ä�FŠF�9˜b¤# d§h¡h¨|Ó&<×&BÐ&BÀÓ"CÓDÀSÕI×jÐjÌTÏ]Ê]Ð[iÓMj€EØ˜  r¥ ¨1¨U°2­Y¨K°q¸¿¹À%»×9WÐ9WÌBÏIÊIËKÐ8XÐXYÐZ^×ZbÑZbÐcnÓZoÐYpÐpuÐvÕvÐvr!   c               ó    € V ^8„  d   QhRRRR/# )r   rn   r9   r   z%Optional[tuple[Path, dict[str, Any]]]r   )r   s   "r   r    r    	  s   € ÷ ñ ˜sð Ð'Lñ r!   c                óþ  € \        \        4      ;_uu_ 4        \        4       P                  RV  R24       F“  p\        \        \        4      ;_uu_ 4        \
        P                  ! VP                  RR7      4      p\        V\        4      '       d0   VP                  R4      V 8X  d   W3uuRRR4       u uuRRR4       # RRR4       K•  	  RRR4       R#   + '       g   i     K²  ; i  + '       g   i     R# ; i)a¥  The run's own archive ``(path, record)`` in the root store, or None. Never raises.

The ONE lookup of a run's archive (named at begin, so its running and terminal records share
one file); never ``latest.json``, which another profile or run may have replaced since. A file
that cannot be read, is not a JSON object, or names another run is not this run's record:
callers treat all of those exactly like a missing archive.
z	update_*_rì   ú	utf-8-sig©Úencodingrn   N)r   ÚOSErrorrÏ   ÚglobÚ
ValueErrorÚjsonÚloadsÚ	read_textr&   r'   r%   )rn   ÚpathrT   s   &  r   Úread_run_recordrÿ   	  s²   € ô 
”'×	Õ	Ü “N×'Ñ'¨)°I°;¸eÐ(DÖEˆDÜœ'¤:×.Õ.ÜŸš D§N¡N¸K NÓ$HÓI�Ü˜f¤d×+Ò+°·
±
¸;Ó0GÈ9Ô0TØ˜<÷ /Ó.÷ 
Ò	ç.Ñ.ñ F÷ 
ñ ÷	 /×.Ð.ú÷ 
Ö	ñ ús*   ˜=C+ÁACÂ*C+ÃC+ÃC(Ã"	C+Ã+C<	c               ó    € V ^8„  d   QhRRRR/# ©r   r   rA   r   r   r   )r   s   "r   r    r      s   € ÷ ñ ˜>ð ¨dñ r!   c                ój  € \        \        4      ;_uu_ 4        ^ RIHp \	        4       pVP                  RRR7       \        W 4      p\        \        V P                  R4      4      4      pVe*   V^,          P                  R4      '       d    RRR4       R# ^ RI
Hp \        P                  ! / V CR\        P                  ! 4       R	V! \        P                  ! 4       4      /C^\        R
7      R,           P!                  R4      pV! W64       \#        V4       RRR4       R#   + '       g   i     R# ; i)zVWrite the open run to disk: a killed update still leaves its own record. Never raises.rÛ   TrÝ   rn   Nr#   ©Ú_process_create_timeÚ
writer_pidÚwriter_create_time©Úindentr   Ú
úutf-8)r   rE   rá   rÜ   rÏ   râ   rò   rÿ   r9   r%   Úhermes_cli.process_identityr  rû   ÚdumpsrZ   rs   Úencoderä   )r   rÜ   rã   rþ   Ústoredr  rØ   s   &      r   Ú_persist_runningr    së   € ä	”)×	Õ	Ý:ä “Nˆ	Ø�‰ ¨tˆÔ4Ü˜Ó)ˆô !¤ T§X¡X¨kÓ%:Ó!;Ó<ˆØÒ &¨¥)§-¡-°×">Ò">Ø÷ 
Ñ	õ 	Eä—:’:ð X ð X |´R·Y²Y³[Ø3Ñ5IÌ"Ï)Ê)Ë+Ó5VñXà%&´ô5à7;õ<ç=C¹VÀG»_ð 	ñ 	�dÔ$Ü�gÔ÷# 
×	×	Ò	ús   ˜A3D!ÂD!ÂB D!Ä!D2	c               ó    € V ^8„  d   QhRRRR/# )r   rT   rA   r   r,   r   )r   s   "r   r    r    0  s   € ÷ ;ñ ;˜ð ;¨Dñ ;r!   c                óˆ  a€ ^ RI Ho / pR F^  w  r#V P                  V4      p\        V\        4      '       g   K.  V^ 8”  g   K7  V P                  V4      pWA9  g   W,          e   KZ  WQV&   K`  	  \
        ;QJ d-    V3R lVP                  4        4       F  '       g   K   R# 	  R# ! V3R lVP                  4        4       4      # )rÉ   )Ú_pid_alive_matchesc              3  ó<   <"  € T F  w  rS! W4      R Jx € K  	  R# 5i)FNr   )Ú.0rH   Úcreate_timer  s   &  €r   Ú	<genexpr>Ú_owner_alive.<locals>.<genexpr><  s%   øé € ð ;Ù'9Ñ#�3ñ " #Ó3¸5Õ@Û'9ùs   ƒTF))rH   Úpid_create_time)r  r  )r  r  r%   r&   rO   ÚanyÚitems)rT   Ú
identitiesrU   Útime_keyrH   r  r  s   &     @r   Ú_owner_aliver  0  s«   ø€ Ý>à€JÛ[‰ˆØ�j‰j˜‹oˆÜ�cœ3×Ô C¨!¦Gð !Ÿ*™* XÓ.ˆKØÔ$¨
­Ô(?Ø"-˜3“ñ \÷ ‹3ô ;Ø'1×'7Ñ'7Ô'9ó;�3Œ3ð ;Š3ð ;ˆ3ô ;Ø'1×'7Ñ'7Ô'9ó;ó ;ð ;r!   c               ó   € V ^8„  d   QhRR/# )r   r   rL   r   )r   s   "r   r    r    @  s   € ÷ ñ Ð$8ñ r!   c                 óÌ  € . p \        \        4      ;_uu_ 4        ^ RIHp \	        4       p\        4       ;'       g    / p\        VP                  R4      R R7      \        ) R  EF’  p\        \        4      ;_uu_ 4        \        P                  ! VP                  RR7      4      p\        V\        4      '       d(   VP                  R4      R	8w  g   \        V4      '       d    RRR4       KŠ  VP                  R
4      ;'       g    . pV'       d6   \        VR,          \        4      '       d   VR,          P                  R4      MRpTP!                  R\#        4       RT;'       g    R R2R7       \        P$                  ! V^\&        R7      R,           P)                  R4      pV! WH4       VP                  R4      VP                  R4      8X  d   \+        V4       V P-                  V4       RRR4       EK•  	  RRR4       V  F3  p\/        RVP                  R4       RVP                  R4       R24       K5  	  V #   + '       g   i     EKì  ; i  + '       g   i     L`; i)a-  Mark ``running`` records whose processes are gone as ``interrupted``; returns them.

The start-of-run reclaimer for the durable running receipt: the next update says plainly
that the previous one was killed and at which stage, instead of reporting its outcome as
whatever ran before it. Never raises.
rÛ   úupdate_*.jsonc                ó6   € V P                  4       P                  # r;   ©ÚstatÚst_mtime©r³   s   &r   Ú<lambda>Ú,reconcile_interrupted_runs.<locals>.<lambda>M  s   € È!Ï&É&Ë(×J[ÒJ[r!   ©rU   Nrõ   rö   r$   rg   r�   r|   Úinterruptedz.process exited during the update (last stage: ÚstartÚ))r$   Úinterrupted_detected_atÚstop_reasonr  r	  r
  rn   u   âš  The previous update (re   z&) was interrupted before it finished (r-  z0); this update completes the work it still owed.éÿÿÿÿ)r   rE   rá   rÜ   rÏ   Úread_latest_receiptÚsortedrù   Ú_RECEIPT_KEEPrû   rü   rý   r&   r'   r%   r  rP   r>   r  r9   r  rä   rQ   Úprint)	r)  rÜ   rã   Úlatestrþ   rT   r�   ÚlastrØ   s	            r   Úreconcile_interrupted_runsr5  @  sç  € ð )+€KÜ	”)×	Õ	Ý:ä “Nˆ	Ü$Ó&×,Ð,¨"ˆÜ˜9Ÿ>™>¨/Ó:Ñ@[Ô\Ô^kÐ]kÐ]lÔmˆDÜœ)×$Õ$ÜŸš D§N¡N¸K NÓ$HÓI�Ü! &¬$×/Ò/°6·:±:¸iÓ3HÈIÔ3UÔYeÐfl×YmÒYmØ÷ %Ñ$ð  Ÿ™ HÓ-×3Ð3°�ß17¼JÀvÈbÅzÔSW×<XÒ<X�v˜b•z—~‘~ fÔ-Ð^b�Ø—‘ mÌ\Ë^Ø,ZÐ[_×[jÐ[jÐcjÐZkÐklÐ*mð ô oäŸ:š: f°QÄÔDÀtÕK×SÑSÐT[Ó\�Ù˜dÔ,Ø—:‘:˜kÓ*¨f¯j©j¸Ó.EÔEÜ! 'Ô*Ø×"Ñ" 6Ô*÷ %Ò$ñ n÷ 
ó& ˆÜÐ)¨&¯*©*°\Ó*BÐ)Cð DØ—*‘*˜]Ó+Ð,Ð,\ð^ö 	_ñ ð Ð÷! %×$Ñ$ú÷ 
×	úsE   šA%IÁ?A%H>Ã$
IÃ.H>Ä
H>ÄAH>Å'BH>Ç.IÈ>IÉ	
IÉI#	Úpreviousr4   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r6  zdict | Noner4   ú
str | Noner   r   r   )r   s   "r   r    r    a  s"   € ÷ %#ñ %# kð %#È*ð %#Ð`dñ %#r!   c           	     ó†  €  \        4       pV '       d0   VP                  P                  \        P                  ! V 4      4       T;'       g    VP
                  Vn        VP                  P                  VP
                  RRR7       VP                  P                  R4      ;'       g    \        4       TP                  R&   \        \        4      ;_uu_ 4        ^ RI
Hp VP                  P                  RV! VP                  R,          4      4       RRR4       V '       g   \        4        V '       d   RV 9  dý   \        \        4      ;_uu_ 4        \        4       ;'       g    / p\        VP                  R	4      ;'       g    / P                  R
4      ;'       g    . 4      pT\        VP                  R4      ;'       g    . 4      ,          pT\        VP                  R4      ;'       g    . 4      ,          p^ RIHp V Uu. uF  qv! V4      '       g   K  VNK  	  upVP                  R&   RRR4       M \(        P+                  V4      Vn        \/        VP                  4       R#   + '       g   i     EL`; iu upi   + '       g   i     LZ; i  \         d"   p\$        P'                  RT4        Rp?R# Rp?ii ; i)u6  Start recording a new update receipt, durably ``running`` until it finalizes.

Nested updates are safe: the previous receipt (if any) is preserved
behind the ContextVar token and comes back when this one finalizes â€”
a nested begin/finalize never drops the outer update's receipt or
correlation. Never raises.rg   N)rn   r$   r#   r4   r  r  rH   Úcarried_manual_servesÚplanÚruntimesÚpending_manual_serves)Úis_reminder_rowz"Could not start update receipt: %s)r_   r   rP   ÚcopyÚdeepcopyr4   r%   r]   r   rE   r  r  r�   r5  r/  rq   Ú#hermes_cli.update_serve_obligationsr>  ÚloggerÚdebugr   r   Úcurrent_tokenr  )	r6  r4   Úreceiptr  ÚpriorÚrowsr>  ÚrowÚexcs	   $$       r   Úbegin_update_receiptrJ  a  sþ  € ðÜ“/ˆßØ�L‰L×Ñ¤§¢¨hÓ 7Ô8Ø!/×!IÐ!I°7×3IÑ3IˆÔØ�‰×Ñ g×&<Ñ&<ÀiÐ]aÐÔbà)0¯©×)9Ñ)9Ð:JÓ)K×)iÐ)iÔOgÓOiˆ�‰Ð%Ñ&Ü”i× Õ ÝHà�L‰L×#Ñ#Ð$5Ñ7KÈGÏLÉLÐY^ÕL_Ó7`Ôa÷ !÷ Ü&Ô(÷ Ð2¸(ÔBÜœ)×$Õ$Ü+Ó-×3Ð3°�Ü˜UŸY™Y vÓ.×4Ð4°"×9Ñ9¸*ÓE×KÐKÈÓL�Øœ˜UŸY™YÐ'>Ó?×EÐEÀ2ÓFÕF�Øœ˜UŸY™YÐ'>Ó?×EÐEÀ2ÓFÕF�ÝOáHLÓ8eÉÀÐP_Ð`c×Pd¿¸ÉÑ8e�—‘Ð4Ñ5÷ %Ð$ð Cô %ŸL™L¨Ó1€GÔÜ�W—\‘\Ö"÷- !× Ð üò" 9f÷ %×$ûô ô Ü�‰Ð9¸3Ô?Ýûðús—   ‚A	J ÁAJ Â(/J Ã:I(ÄJ Ä!J Ä3J Å1JÆJÆ$JÇ*JÇ,JÈI<ÈI<ÈJÈ-J É(I9	É3	J É<JÊJ	ÊJ ÊJ ÊK ÊJ;Ê;K c               ó   € V ^8„  d   QhRR/# ra   r   )r   s   "r   r    r    ‰  s   € ÷ 'ñ ' ñ 'r!   c                 ó¨   € \         P                  4       p V e:   V P                  P                  R4      R8X  d   \        V P                  4       R# R# R# )zSRe-assert the open run on disk (the completion child calls this after resuming it).Nr$   rg   )r   r%   r   r  r5   s    r   Úpersist_running_receiptrM  ‰  s>   € ä�l‰l‹n€GØÒ˜wŸ|™|×/Ñ/°	Ó:¸iÔGÜ˜Ÿ™Ö&ñ  HÑr!   c               ó   € V ^8„  d   QhRR/# ra   r   )r   s   "r   r    r    ›  s   € ÷ lñ l Tñ lr!   c                ó¢   € \        R\        ;QJ d    R V  4       F  '       g   K   RM	  RM! R V  4       4      '       d	   R4       R# R4       R# )z^Mark the build stage from the owed ``(step, reason)`` follow-ups: failed only for a build one.Úbuildc              3  ó8   "  € T F  w  rV\         9   x € K  	  R # 5ir;   )ÚBUILD_FOLLOWUPS)r  r�   rë   s   &  r   r  Ú%record_build_stage.<locals>.<genexpr>�  s   é € Ð)[ÑQZÁgÀd¨$´/Ö*AÓQZùs   ‚TFr¯   r.   N)Úrecord_stager  )r›   s   &r   Úrecord_build_stagerU  ›  s4   € ä�§c£cÑ)[ÑQZÓ)[§c§c¢cÑ)[ÑQZÓ)[×&[Ò&[˜(ÖkÐajÖkr!   Úretryz-the next launch or `hermes update` retries itc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r�   r9   r…   rV  r   r   r   )r   s   "r   r    r       s)   € ÷ 'ñ '˜#ð ' sð '°cð 'Ðptñ 'r!   c          	     óX  € RP                  \        V4      P                  4       4      R,          ;'       g    Rp\        RV  RV RV R2RR	7       \        P                  4       pVf   R
# \        RRV  2W4       \        P                  4       pVe   \        VP                  4       R
# R
# )u  A post-commit step failed: print âš , keep the run a success, and say what is still owed.

The code already committed, so the update does not fail; the step's own obligation (the
source tail, the fleet restart, the launch-time bytecode sweep) stays armed and the next
launch or ``hermes update`` retries it. Never raises. The printed line is a protocol: the
Desktop hand-offs (scripts/desktop-update/posix.sh, windows.ps1) parse ``Update follow-up
'<step>' did not finish:`` to report every owed step, so keep it one whole line.
Ú ºNiô  Nr¯   u     âš  Update follow-up 'z' did not finish: z (r+  T©ÚflushNrœ   zupdate followup )	Újoinr9   Úsplitr2  r   r%   Ú_recordr  r   )r�   r…   rV  r6   s   &&$ r   Úrecord_followupr`     s—   € ð �X‰X”c˜&“k×'Ñ'Ó)Ó*¨4Õ0×<Ð<°H€FÜ	Ð$ T FÐ*<¸V¸HÀBÀuÀgÈQÐ
OÐW[Õ\Ü�l‰l‹n€GØ‚ÙÜˆJÐ*¨4¨&Ð1°4Ô@Ü�l‰l‹n€GØÒÜ˜Ÿ™Ö&ñ r!   c               ó$   € V ^8„  d   QhRRRRRR/# r™   r   )r   s   "r   r    r    ´  s!   € ÷ ñ ˜Sð ¨#ð °$ñ r!   c                óž   € \        RRV  2RRV RRP                  \        V4      P                  4       4      R,          /4       \	        4        R# )	a^  The code committed, but something only the user can do is still owed. Never raises.

Unlike a follow-up nothing retries it (a stash whose restore conflicted stays parked until the
user re-applies it), so the run can never be a plain success: it finalizes ``partial`` and
``hermes update`` exits 1, as #122557 established for an unrestored autostash.
r–   zupdate user action r¼   r�   r…   rY  rZ  N)r_  r]  r9   r^  rM  )r�   r…   s   &&r   Úrecord_user_actionrc  ´  sL   € ô ˆFÐ)¨$¨Ð0°-À&È$ÐPXÐZ]×ZbÑZbÔcfÐgmÓcn×ctÑctÓcvÓZwÐx|ÕZ}ÐA~ÔÜÖr!   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   rn   r9   r�   r…   r   r   r   )r   s   "r   r    r    ¿  s(   € ÷ #ñ # sð #°#ð #¸sð #Àtñ #r!   c           	     óÞ  € \        V 4      pVf   R# Tw  rEVP                  R. 4      P                  RVRVR\        4       /4       \        P
                  ! V^\        R7      R,           P                  R4      p\        \        4      ;_uu_ 4        ^ R	I
Hp V! WF4       \        4       ;'       g    / P                  R
4      V 8X  d   \        V4       RRR4       R#   + '       g   i     R# ; i)zbA follow-up that failed after the run's receipt was finalized lands on that receipt. Never raises.Nr›   r�   r…   r€   r  r	  r
  rÛ   rn   )rÿ   r�   rQ   r>   rû   r  r9   r  r   rE   rá   rÜ   r/  r%   rä   )rn   r�   r…   Úfoundrþ   rT   rØ   rÜ   s   &&&     r   Úamend_terminal_followuprg  ¿  s´   € ä˜IÓ&€EØ‚}ÙØ�L€DØ
×Ñ�k 2Ó&×-Ñ-¨v°t¸XÀvÈtÔUaÓUcÐ.dÔeÜ�zŠz˜&¨´CÔ8¸4Õ?×GÑGÈÓP€GÜ	”)×	Õ	Ý:á�dÔ$ÜÓ!×'Ð' R×,Ñ,¨[Ó9¸YÔFÜ˜'Ô"÷ 
×	×	Ò	ús   ÂACÃC,	c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   rn   r2   r�   r9   r…   rV  r   r   r   )r   s   "r   r    r    Ï  s0   € ÷ 9ñ 9˜Mð 9°ð 9¸cð 9ÈCð 9ÐTXñ 9r!   c                óz   € \        W3/ VB  \        P                  4       f   V '       d   \        WV4       R# R# R# )zàA post-commit step failed: record it on the run while its receipt is open, else amend the
run's closed receipt. Amending an OPEN run would append a second copy beside the one
``record_followup`` just persisted. Never raises.N)r`  r   r%   rg  )rn   r�   r…   rV  s   &&&,r   Úowe_followuprj  Ï  s1   € ô �DÑ* EÒ*Ü‡|�|ƒ~Ò§)Ü 	°Ö8ñ #,Ñr!   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   Úmethodr9   ÚwhatÚargsr	   Úkwargsr   r   r   )r   s   "r   r    r    Ø  s/   € ÷ ;ñ ;�Cð ;˜sð ;¨3ð ;¸#ð ;À$ñ ;r!   c                óT  €  ^ RI p\        P                  4       pVf   R# VP                   ! V4      pVP                  ! VP                  4      Vn        \        W`4      ! V/ VB  \        P                  V4       R#   \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)uD  Invoke ``method`` on the active receipt; no-op when none, never raises.

Copy-on-write, same rule as pm.receipt: a copied context (copy_context,
asyncio.to_thread) inherits the SAME receipt object â€” mutate a clone
and re-set it in THIS context only, so a child's records never leak
into (or corrupt) the parent's receipt.
NzCould not record %s: %s)
r?  r   r%   r@  r   Úgetattrr   rE   rB  rC  )rl  rm  rn  ro  r?  r6   ÚclonerI  s   &&*,    r   r_  r_  Ø  s   € ð;Ûä—,‘,“.ˆØŠ?ÙØ—	’	˜'Ó"ˆØ—]’] 7§<¡<Ó0ˆŒ
Ü�Ô Ð/¨Ò/Ü�‰�UÖøÜô ;Ü�‰Ð.°×:Ò:ûð;ús   ‚A;  AA; Á;B'ÂB"Â"B'c               ó(   € V ^8„  d   QhRRRRRRRR/# r{   r   )r   s   "r   r    r    î  s(   € ÷ =ñ =�cð =˜tð =¨Sð =¸$ñ =r!   c                ó(   € \        RRV  2WV4       R# )z@Record one update step outcome. No-op when no receipt is active.r�   zupdate step N©r_  )r|   r}   r~   s   &&&r   Úrecord_steprv  î  s   € äˆF�l 4 &Ð)¨4°VÖ<r!   c               ó$   € V ^8„  d   QhRRRRRR/# r„   r   )r   s   "r   r    r    ó  s!   € ÷ 9ñ 9�cð 9 3ð 9¨4ñ 9r!   c                ó&   € \        RRV  2W4       R# )z5Record a skipped step WITH the reason it was skipped.r‡   zupdate skip Nru  )r|   r…   s   &&r   Úrecord_skipry  ó  s   € äˆF�l 4 &Ð)¨4Ö8r!   c               ó(   € V ^8„  d   QhRRRRRRRR/# rŠ   r   )r   s   "r   r    r    ø  s(   € ÷ ñ �sð  Sð °3ð ¸4ñ r!   c                ó<   € \        RRV  2W3/ VB  \        4        R# )zWMark the END of a pipeline stage (``success``/``failed``/``skipped``) with a timestamp.r�   zupdate stage N)r_  rM  )r|   r$   r‹   s   &&,r   rT  rT  ø  s    € äˆG�} T FÐ+¨TÑD¸eÒDäÖr!   c               ó$   € V ^8„  d   QhRRRRRR/# r“   r   )r   s   "r   r    r    ÿ  s!   € ÷ 6ñ 6�Sð 6 ð 6¨ñ 6r!   c                ó&   € \        RRV  2W4       R# )z5Set one top-level receipt field (e.g. ``initiator``).r–   zupdate fact Nru  )rU   r”   s   &&r   Úrecord_factr~  ÿ  s   € äˆF�l 3 %Ð(¨#Ö5r!   c               ó    € V ^8„  d   QhRRRR/# )r   ro  r	   r   r   r   )r   s   "r   r    r      s   € ÷ Jñ J Sð J¨Tñ Jr!   c                 ó   € \        R/ V B  R# )z=Record the gateway restart phase outcome (see UpdateReceipt).N)r¸   zgateway restart resultru  )ro  s   ,r   Úrecord_gateway_restartr�    s   € äÑIÀ&ÔIr!   c               ó    € V ^8„  d   QhRRRR/# )r   r…   r9   r   r   r   )r   s   "r   r    r    	  s   € ÷ Cñ C˜sð C tñ Cr!   c                ó(   € \        RRV  2RV 4       R# )a›  Name the exit that is about to stop this run, as one closed token (``stop_class``).

Called on the line before the ``sys.exit``/raise it names, so the last one recorded is the
exit that fired. The token must be one of ``shared_metrics_contract.UPDATE_STOP_CLASSES``
(anything else is ignored by the metric); the human ``stop_reason`` and printed text are
untouched. No-op when no receipt is open; never raises.
r–   zupdate stop Ú
stop_classNru  )r…   s   &r   Úrecord_stop_reasonr…  	  s   € ô ˆF�l 6 (Ð+¨\¸6ÖBr!   z$Permission denied(?! *\()|\bEACCES\bc               ó    € V ^8„  d   QhRRRR/# )r   rI  ÚBaseExceptionr   r2   r   )r   s   "r   r    r      s   € ÷ 
?ñ 
?˜mð 
?°ñ 
?r!   c                ó&  € \        V \        P                  4      '       g   R# V P                  ;'       g    V P                  ;'       g    Rp\        V\
        4      '       d   VP                  RR4      M
\        V4      p\        V P                  \        \        34      '       d&   V P                   Uu. uF  p\        V4      NK  	  upM,\        V P                  ;'       g    R4      P                  4       p\        WV P                  4      # u upi )z»The closed stop token for a git ``CalledProcessError`` that is about to end the run, or None.

Reads only the failed argv and fixed git/Hermes phrases in its output, never stores either.
NrN   r
  Úreplace)r&   Ú
subprocessÚCalledProcessErrorÚstderrÚoutputrÙ   Údecoder9   Úcmdrq   Útupler^  Úgit_output_stop_classÚ
returncode)rI  r�  Úpartrf   s   &   r   Úgit_error_stop_classr”    sÃ   € ô
 �cœ:×8Ñ8×9Ò9ÙØ�Z‰Z×+Ð+˜3Ÿ:™:×+Ð+¨€FÜ2<¸VÄU×2KÒ2KˆV�]‰]˜7 IÔ.ÔQTÐU[ÓQ\€FÜ.8¸¿¹Ä4ÌÀ-×.PÒ.P #§'¢'Ó*¡'˜$ŒC�ŽI¡'Ò*ÔVYÐZ]×ZaÑZa×ZgÐZgÐegÓVh×VnÑVnÓVp€DÜ  ¨s¯~©~Ó>Ð>ùò +s   Â4Dc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r�  r9   rf   z	list[str]r’  úOptional[int]r   r2   r   )r   s   "r   r    r    &  s)   € ÷ ñ  #ð ¨Yð ÀMð Ð]jñ r!   c                óÜ   € RV 9   d
   RV 9   d   R# \         P                  V 4      '       d   R# V^|8X  d
   RV 9   d   R# RV 9   d   R# R	V9   d   R
# 0 Rm\        V4      ,          '       d   R# R# )z\:func:`git_error_stop_class` for a git call that returned instead of raising (``_git_run``).z
index.lockzFile existsÚgit_index_lockedÚpermission_deniedztimed out afterÚgit_timeoutzNo space left on deviceÚ	disk_fullÚstashÚlocal_changes_blockedÚcheckout_move_failedN>   Úmerger   Úcheckout)Ú_GIT_FILE_PERMISSIONÚsearchr   )r�  rf   r’  s   &&&r   r‘  r‘  &  se   € à�vÔ -°6Ô"9Ù!Ü×"Ñ" 6×*Ò*Ù"Ø�SÔÐ.°&Ô8ÙØ  FÔ*ÙØ�$„Ù&Ú%¬¨D«	×1Ô1Ù%Ùr!   c               ó   € V ^8„  d   QhRR/# )r   r   r8  r   )r   s   "r   r    r    7  s   € ÷ Oñ O Zñ Or!   c                 ó„  € ^ RI Hp HpHp V! V! 4       P	                  4       4      pVP
                  f   R# \        P                  ! 4       pVP                  V\        P                  ! 4       39   d   R# V ! 4       \        P                  ! 4       0R^ ^V0,
          pWSP                  VP                  0,          '       d   R# R# )aa  ``delegate`` (the hand-off launched this process as its update child) or ``partner`` when
the update marker names the Desktop hand-off this process runs under, else None.

For an exit before the receipt opens, where this process may NOT hold the lock: at the
update-lock refusal the marker belongs to whichever update holds it, so "a pid other than
ours" (update_cmd._record_update_initiator, which runs under the lock) would call every
refusal Desktop-started. The claim is ours only when it names us as its delegate (the posix and
Windows hand-offs write that line before the update runs) or names our hand-off partner on
line 1 or the delegate line (``HERMES_UPDATE_HANDOFF_PID``, the Tauri updater; our parent, a
launcher between the hand-off and us). The marker is read raw: no liveness probe and no
cleanup (those are lock policy, not a metrics side effect).
)Ú_handoff_pidÚ_parse_markerÚupdate_marker_pathNÚdelegateÚpartner)Úhermes_cli.update_lockr¥  r¦  r§  Ú
read_bytesre   rZ   rs   Údelegate_pidÚgetppidrH   )r¥  r¦  r§  ÚmarkerrH   Úpartnerss         r   Ú_started_by_handoff_partnerr°  7  sœ   € ÷ WÑVáÑ-Ó/×:Ñ:Ó<Ó=€FØ×ÑÒ ÙÜ
�)Š)‹+€Cð ×Ñ˜s¤B§J¢J£LÐ1Ô1ÙÙ“¤§
¢
£Ð-°°q¸!¸SÐ0AÕA€HØ §J¡J°×0CÑ0CÐ#D×DÔDˆ9ÐNÈ$ÐNr!   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r…   r9   r$   r   r   r   )r   s   "r   r    r    R  s!   € ÷ $ñ $¨ð $°cð $¸dñ $r!   c                óÂ  € \        \        4      ;_uu_ 4        \        4       pR^R\        P                  ! 4       P
                  RTRTRVR8X  d   RMRRV R	/ R
. R. R. /
p\        \        4      ;_uu_ 4        \        4       pV'       d   RVR&   VR8X  d   RVR&   RRR4       ^ RIHp V! V4       RRR4       R#   + '       g   i     L(; i  + '       g   i     R# ; i)az  Count an exit that fires before this run's receipt opens, in shared metrics only.

No receipt is written, so the exit behaves exactly as before: at the update-lock refusal
``latest.json`` and the running record belong to the update holding the lock (opening one
would replace its pointer and reconcile its archive), and the Git-operation refusal runs before
the receipt, plan and snapshot by design. The row is derived from the same fields a final
receipt carries (``outcome`` is ``refused`` or ``failed``), including the initiator, so a
Desktop-started refusal reads ``kind=desktop`` like the same run's receipt would. Never raises.
rd   rn   re   r#   r$   Úrefusedr¯   r„  rh   r�   rj   rm   ÚdesktopÚ	initiatorr¨  N©Úrecord_update_receipt)	r   rE   r>   rt   ru   rv   r°  Ú.hermes_cli.observability.shared_metrics_updater·  )r…   r$   r<   r   Úclaimr·  s   &&    r   Úrecord_stop_without_receiptrº  R  sÄ   € ô 
”)×	Õ	Ü‹nˆà�a˜¤d§j¢j£l×&6Ñ&6¸ÀcÈ=ÐZ]Ø G¨yÔ$8‘y¸hØ˜& ,°°H¸bÀ'È2ÈwÐXZð
ˆô
 ”i× Õ Ü/Ó1ˆEßØ$-��[Ñ!Ø˜
Ô"ð #+��Y‘÷ !õ 	Yá˜dÔ#÷# 
Ñ	÷ !× ú÷ 
×	Ð	ús$   ˜ACÁ6$B:	ÂCÂ:C
ÃCÃC	c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r$   r9   rm   r§   r-  r   úOptional[Path]r   )r   s   "r   r    r    p  s0   € ÷ [ñ [ Sð [°ð [ÐRUð [Ð_mñ [r!   c                óâ  € \         P                  4       pVf   R# \        P                  ! V4      p\        P                  ! VP                  4      Vn        \        VRR4      p Ve   \         P                  V4       M\         P                  R4         VP                  V 4       V'       d   W$P                  R&   VP                  \        \        VP                  P                  R4      4      &   \        VP                  4       Ve   WP                  R&   ^ RIHp RVP                  9   d)   RVP                  P                  R4      ;'       g    . /pM\!        4       ;'       g    / pV! V4      pV'       d   W„P                  R&    ^ R	IHp	 V	P'                  VP(                  R
R7      p
\+        V
\,        4      '       d¾   R F0  pV
P                  V4      f   K  W«,          VP                  RV 2&   K2  	  V
P                  R4      e   V
P                  R4      VP                  R&   V
P                  R4      '       d   V
R,          VP                  R&   V
P                  R4      e   V
R,          VP                  R&   \5        4       pTP7                  R
R
R7       ^ RIHp \=        YÔP                  4      p\>        P@                  ! TP                  ^\        R7      R,           PC                  R4      pT! TT4       \E        \.        4      ;_uu_ 4        \G        T4       RRR4       \I        T4       \K        TP                  4       T#   \         d    \         P                  R4        ELÚi ; i  \.         d"   p\0        P3                  RT4        Rp?ELRp?ii ; i  + '       g   i     Lˆ; i  \.         d0   p\0        PM                  RY4       \O        RT 24        Rp?R# Rp?ii ; i)aÀ  Finalize + persist the receipt (``success``/``partial``/``failed``/``refused``); path or None.

Exactly-once by construction: the context's receipt is popped first, so a second call (e.g. the
command-boundary safety net after an inner path already finalized) is a no-op returning None.
The receipt is popped via its OWN begin token, so a nested update's finalize RESTORES the outer
update's open receipt and correlation instead of discarding them.
NrD  r-  rn   rm   )Úretain_receipt_manual_servesr:  r=  )rE  T)ÚconsumeÚpm_r$   Úpm_sync_outcomeÚwarningsÚpm_warningsÚrefusalÚ
pm_refusalz!pm sync-section embed skipped: %srÝ   rÛ   r  r	  r
  z'Could not write update receipt (%s): %su"     âš  Update receipt not written: )Úvenv_rebuildÚplugin_bisectÚfeature_listrj   Ú	exit_code)(r   r%   r?  r@  r   rq  r   r   rú   r¾   r   r9   r)   rA  r¾  Úpopr/  ÚpmrE  Úlast_for_updater4   r&   r'   rE   rB  rC  rÏ   râ   rá   rÜ   rò   rû   r  r  r   rä   Ú_prune_old_receiptsÚ_publish_shared_metricsÚwarningr2  )r$   rm   r-  r6   rE  r   r¾  rF  ÚpendingÚ
pm_receiptÚsyncrU   rI  rã   rÜ   rþ   rØ   s   &&&              r   Úfinalize_update_receiptrÓ  p  s  € ô �l‰l‹n€GØ‚ÙÜ�iŠi˜Ó €GÜ—=’= §¡Ó.€G„LÜ�G˜_¨dÓ3€EðØÒÜ�N‰N˜5Õ!ä�L‰L˜Õð
DØ×Ñ˜Ô!ßØ*5�L‰L˜Ñ'ð :A¿¹Œ
”3�w—|‘|×'Ñ'¨Ó4Ó5Ñ6Ü˜wŸ|™|Ô,ØÒØ$)�L‰L˜Ñ!õ 	UØ" g§l¡lÔ2Ø,¨g¯l©l×.>Ñ.>Ð?VÓ.W×.]Ð.]Ð[]Ð^‰Eä'Ó)×/Ð/¨RˆEÙ.¨uÓ5ˆßØ4;�L‰LÐ0Ñ1ð	CÝ0à×-Ñ-¨g×.DÑ.DÈdÐ-ÓSˆDÜ˜$¤×%Ò%Ûb�CØ—x‘x “}Ô0Ø48µI˜Ÿ™ s¨3¨% [Ó1ñ cð —8‘8˜IÓ&Ò2Ø6:·h±h¸yÓ6I�G—L‘LÐ!2Ñ3Ø—8‘8˜J×'Ò'Ø26°zÕ2B�G—L‘L Ñ/Ø—8‘8˜IÓ&Ò2Ø15°iµ�G—L‘L Ñ.ô !“Nˆ	Ø�‰ ¨tˆÔ4õ
 	;ô ˜§L¡LÓ1ˆÜ—:’:˜gŸl™l°1¼cÔBÀTÕI×QÑQÐRYÓZˆÙ�d˜GÔ$Ü”i× Õ Ü˜'Ô"÷ !ä˜IÔ&Ü §¡Ô-ØˆøôE ô ô 	�‰�T×ðûô` ô 	CÜ�L‰LÐ<¸c×BÒBûð	Cú÷ !× ûô
 ô ô 	�‰Ð@À'ÔOÜÐ2°3°%Ð8Ô9Ýûðúsš   Á$M Á>M ÂN4 Â.B#N4 ÅN4 Å(N4 Å;N4 Æ
AM2 ÇA#M2 É?M2 Ê BN4 ÌN!Ì!)N4 Í M/Í.M/Í2NÍ=NÎN4 ÎNÎN4 Î!N1	Î,N4 Î4O.Î?$O)Ï)O.c               ó   € V ^8„  d   QhRR/# ©r   r   úOptional[bool]r   )r   s   "r   r    r    Î  s   € ÷ Fñ F ñ Fr!   c                 óz  € \        \        P                  P                  R4      RR4      p V f   R#  V ! 4       p\        T4      \        Jd   R# R F,  p\        T\        4      '       d   TP                  T4      MRpK.  	  \        T\        4      ;'       d    TP                  R4      RJ #   \         d     R# i ; i)zµShared-metrics consent via the ALREADY-LOADED config module (never an import: this interpreter
predates the checkout swap). None when it cannot tell (not loaded, unreadable config).zhermes_cli.configÚread_raw_config_readonlyNÚenabledT)Ú	telemetryÚshared_metrics)rq  rr   Úmodulesr%   rE   Útyper'   r&   )ÚreaderÚconfigrU   s      r   Ú_collection_enabled_nowrà  Î  s£   € ô ”S—[‘[—_‘_Ð%8Ó9Ð;UÐW[Ó\€FØ‚~ÙðÙ“hˆô ˆFƒ|œ4ÓÙÛ.ˆÜ$.¨v´t×$<Ò$<�—‘˜C”À$Šñ /ä�fœdÓ#×EÐE¨¯
©
°9Ó(=ÀÐ(EÐEøô ô Úðús   ²B+ Â+B:Â9B:zƒ(?:[A-Z][A-Za-z0-9_]{0,63}:(?: \[(?:Errno|WinError) \d+\])?|historical takeover preparation failed|Windows gateway recovery failed)z[a-z][a-z0-9_]{0,39}c               ó    € V ^8„  d   QhRRRR/# )r   r   rA   r   r   )r   s   "r   r    r    è  s   € ÷ &ñ &˜.ð &¨^ñ &r!   c                óF  a € V 3R lR 4       w  rp\        V\        4      '       d   TM/ p\        V\        4      '       d   TM/ p\        V\        4      '       d   TMRp\        P	                  V4      pS P                  R4      pS P                  R4      p	/ RS P                  R4      bR	S P                  R	4      bR
S P                  R
4      bRS P                  R4      bRS P                  R4      bRS P                  R4      R8X  d   RMRbRRVP                  R4      /bRS P                  R4      ;'       g    R U
Uu. uF<  p
\        V
\        4      '       g   K  R Uu/ uF  q»V
9   g   K  WºV,          bK  	  upNK>  	  upp
bRS P                  R4      ;'       g    R Uu. uFQ  p\        V\        4      '       g   K  VP                  R4      R8X  g   K3  RRR\        VP                  R4      4      /NKS  	  upbRS P                  R4      ;'       g    R Uu. uF.  p\        V\        4      '       g   K  RVP                  R4      /NK0  	  upbR\        V\        4      '       d   \        P                  V4      '       d   TMRbR\        V	\        4      '       d   \        V	\        4      '       g   T	MRbRV'       d   VP                  ^ 4      MV'       d   RMRbR\        S P                  R4      4      bRR Uu/ uF  q»\        VP                  V4      4      bK  	  upbRS P                  R4      ;'       g    R Uu. uF7  p\        V\        4      '       g   K  VP                  R4      R8X  g   K3  RR/NK9  	  upb# u upi u upp
i u upi u upi u upi u upi ) aq  Only what shared_metrics_update.update_receipt_fields reads; never argv or step text.

Every field the classifier reads is kept in closed form so a parked run classifies exactly as
the same run finalized in-process: the exit's ``stop_class`` token, the exit code, the stop
reason's leading label (``-`` for any other text), and flags for the restart/user-action facts.
c              3  óF   <"  € T F  pSP                  V4      x € K  	  R # 5ir;   ©r%   )r  rU   r   s   & €r   r  Ú"_metric_receipt.<locals>.<genexpr>ï  s   øé € Ð'rÑAq¸#¨¯©°¯¨ÓAqùs   ƒ!rh   rl   r-  rN   r„  rÉ  rd   rn   re   r#   r$   rµ  r´  NÚcommit_dater�   r|   rj   Ú	admissionr}   rm   ÚstateÚ-r¼   Úruntime_outcomesr¯   )rh   rl   r-  r   )r|   r$   r€   Úmode)r£   r¤   r¢   )r&   r'   r9   Ú_PARKED_REASON_LABELÚmatchr%   r,   Ú_STOP_CLASS_TOKENÚ	fullmatchrO   Úgroup)r   Úraw_preÚraw_restartÚ
raw_reasonÚpreÚrestartr…   Úlabelr„  rÉ  ÚmarkrU   r�   rH  s   f             r   Ú_metric_receiptrø  è  s‚  ø€ ô (sÑAqÓ'rÑ$€G˜*Ü%/°¼×%>Ò%>™'ÀB€CÜ-7¸ÄT×-JÒ-J™kÐPR€GÜ *¨:´s× ;Ò ;‘*À€FÜ ×&Ñ& vÓ.€EØ—‘˜,Ó'€JØ—‘˜Ó%€IðØ�$—(‘(˜8Ó$ðà�T—X‘X˜kÓ*ðà,8¸$¿(¹(À<Ó:Pðð 	�t—x‘x Ó.ðð 1:¸4¿8¹8ÀIÓ;Nðð 	 $§(¡(¨;Ó"7¸9Ô"D‘YÈ$ð	ð
 	�} c§g¡g¨mÓ&<Ð=ðð 	àŸ™ Ó*×0Ð0¨bÐ0ô
á0�´J¸tÄT×4Jô YÑ'HÓXÑ'H ÐSWÉKŒ^ˆS�s•)Š^Ñ'HÔXÙ0ò
ðð 	àŸ™ Ó)×/Ð/¨RÐ/ó
á/�´:¸dÄD×3Iô >ØNRÏhÉhÐW]ÓN^ÐbmÑNmô >ˆV�[ $¬¨T¯X©X°d«^Ó(<Ó=Ù/ñ
ðð 	¸¿¹À'Ó9J×9PÐ9PÈbÐ9PÓjÑ9P°#ÔT^Ð_bÔdh×TiÔ-�7˜CŸG™G GÓ,Ó-Ñ9PÑjðð 	¤J¨z¼3×$?Ò$?ÔDU×D_ÑD_Ð`j×DkÒDk‘jÐquðð  	¤*¨Y¼×"<Ò"<ÄZÐPYÔ[_×E`ÒE`‘YÐfjð!ð" 	¯�u—{‘{ 1”~¿F±SÈð#ð$ 	”t˜DŸH™H ]Ó3Ó4ð%ð& 	ÑCpÓqÑCp¸C¤ g§k¡k°#Ó&6Ó!7Ò7ÑCpÑqð'ð( 	Ø-1¯X©XÐ6HÓ-I×-OÐ-OÈRÐ-Oó
Ù-O cÜ˜#œt×$ô "Ø),¯©°Ó);¸xÑ)Gô "ˆY˜Ó!Ñ-Oñ
ð)ð ùò Yùó
ùò
ùò kùò
 rùò
sZ   Ä?N	
ÅN	
Å NÅ-NÅ:N	
Æ#NÇ NÇ"NÈNÈ8NË?#NÍNÍ NÍ8NÎN	
c               ó   € V ^8„  d   QhRR/# r+   r   )r   s   "r   r    r      s   € ÷ ñ  Dñ r!   c                 ó4   €  ^ RI p R#   \         d     R# i ; i)a  Whether this interpreter can load the config reader the recorder's consent gate uses.

False in the bare ``-I -S`` bootstrap interpreter that finalizes an update whose dependency
preparation failed (update_completion._settle_after_commit): it has the new tree but no
third-party packages, so ``hermes_cli.config`` dies on ``ruamel``. Only asked of an interpreter
that runs the new tree (never the pre-pull one, which must import nothing); the recorder's
pre-gate imports the same module next, so a working interpreter loads nothing extra.NFT)Úhermes_cli.configÚImportError)Ú
hermes_clis    r   Ú_consent_reader_importablerþ    s#   € ðÛ ñ øô ô Úðús   ‚ ˆ–c               ó   € V ^8„  d   QhRR/# rÕ  r   )r   s   "r   r    r       s   € ÷ ñ  .ñ r!   c                 óª   € \        4       p V e   V # ^ RIHp  V! 4       R,          P                  4        R#   \         d     R# \
         d     R# i ; i)zõConsent as far as an interpreter without the config reader can tell: the loaded module's
answer if one is loaded, False when the profile has no config.yaml (the shipped default is off),
else None (unknowable here; the next normal start decides).NrÒ   zconfig.yamlF)rà  rÎ   rÓ   r#  ÚFileNotFoundErrorrø   )rÙ  rÓ   s     r   Ú_bare_collection_enabledr     sW   € ô &Ó'€GØÒØˆÝ0ðÙ	Ó	˜]Õ	*×0Ñ0Ô2ñ
 øô	 ô ÚÜô Úðús   ˜6 ¶AÁAÁAÁAc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   rA   rÙ  rÖ  r   r   r   )r   s   "r   r    r    2  s&   € ÷ vñ v˜~ð v¸ð vÈ4ñ vr!   c                ó^  € ^ RI Hp ^ RIHp V! 4       R,          R,          R,          pVRJ d   ^ RIpVP                  VRR	7       R# VP                  RRR
7       V! W@P                  R4       R2,          \        P                  ! \        V 4      \        R7      P                  4       4       R# )zöKeep the bounded fields for the next Hermes start (stdlib only): ``report_pending_updates``
records them when collection is on, ``begin_process`` purges them when it is off. Collection
known off: park nothing and purge what an earlier run parked.rÒ   rÛ   rÚ  rÛ  Úpending_updatesFNT)Úignore_errorsrÝ   rn   rì   r   )rÎ   rÓ   rá   rÜ   ÚshutilÚrmtreerâ   r%   rû   r  rø  r9   r  )r   rÙ  rÓ   rÜ   rÐ  r  s   &&    r   Ú_park_metric_receiptr	  2  sŠ   € õ 1Ý6áÓ +Õ-Ð0@Õ@ÐCTÕT€GØ�%ÓÛà�‰�g¨TˆÔ2ÙØ‡M�M˜$¨€MÔ.Ù�'Ÿx™x¨Ó4Ð5°UÐ;Õ;¼T¿ZºZÌÐX\ÓH]ÔgjÔ=k×=rÑ=rÓ=tÖur!   c               ó    € V ^8„  d   QhRRRR/# r  r   )r   s   "r   r    r    C  s   € ÷ $ñ $ .ð $°Tñ $r!   c                óZ  € \        \        4      ;_uu_ 4        V P                  R4      ;'       g    / V P                  R4      ;'       g    / r!V P                  R4      \        P                  ! 4       8X  d\   VP                  R4      '       d&   VP                  R4      VP                  R4      8X  g    \        V \        4       4        RRR4       R# \        4       '       g    \        V \        4       4        RRR4       R# ^ RI	H
p V! V 4       RRR4       R#   + '       g   i     R# ; i)aU  hermes.update.run/stage from this FINAL receipt; must never fail or slow the update.

Rows are emitted only by an interpreter that can read consent with the real config reader.
Any other interpreter parks the bounded fields instead, and the next normal start applies the
collection gate (records them, or purges them when collection is off).rh   ri   rH   ÚshaNr¶  )r   rE   r%   rZ   rs   r	  rà  rþ  r  r¸  r·  )r   rô  Úpostr·  s   &   r   rÎ  rÎ  C  sÔ   € ô 
”)×	Õ	Ø—H‘H˜\Ó*×0Ð0¨b°$·(±(¸=Ó2I×2OÐ2OÈRˆTØ�8‰8�E‹?œbŸiši›kÔ)°3·7±7¸5·>²>ÀcÇgÁgÈeÃnÐX\×X`ÑX`ÐafÓXgÔFgô ! Ô'>Ó'@ÔAØ÷ 
Ñ	ô *×+Ò+ô ! Ô'?Ó'AÔBØ÷ 
Ñ	õ 	Yá˜dÔ#÷ 
×	×	Ò	ús$   ˜2DÁADÂ:DÃ%DÄDÄD*	c               ó    € V ^8„  d   QhRRRR/# )r   rn   r9   r   úOptional[dict[str, Any]]r   )r   s   "r   r    r    Z  s   € ÷ =ñ = ð =Ð)Añ =r!   c                óv   € \         P                  \        V 4      4      pVe   \        P                  ! V4      # R# )u6  The terminal record this process finalized for ``update_id``, published or not.

The completion child answers its parent from this when the receipt store refused the
terminal write: the run is still correlated and terminal, only its archive is missing
(already reported by ``âš  Update receipt not written``).
N)r   r%   r9   r?  r@  )rn   r   s   & r   Úfinalized_receiptr  Z  s/   € ô �>‰>œ#˜i›.Ó)€DØ"&Ò"2Œ4�=Š=˜ÓÐ<¸Ð<r!   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rÉ  r–  r-  r9   r   r¼  r   )r   s   "r   r    r    e  s(   € ÷ Eñ E¨}ð EÐRUð EÐ_mñ Er!   c                óú  € \         P                  4       pVf   R# V R	9   d   RM-V ^8X  d   RM$VP                  P                  R4      '       d   RMRpV e‰   \        \        4      ;_uu_ 4        \
        P
                  ! V4      p\
        P                  ! VP                  4      Vn        \        V 4      VP                  R&   \         P                  V4       RRR4       \        W1R7      #   + '       g   i     L; i)
u¨  Command-boundary safety net: persist a still-open receipt, if any. Never raises.

``hermes update`` has many early ``sys.exit`` paths (preflight refusals, venv-holder refusal,
fetch failure) predating the inner finalize calls; finalizing here means refused/failed runs â€”
where a receipt matters most â€” leave a record. Exit 0/None â†’ ``success``, exit 2 â†’ ``refused``
(preflight convention), else â†’ ``failed`` (``partial`` when the run committed and only owes a
user action, see ``record_user_action``).

No-op when no receipt is open (the inner paths already finalized â€” exactly-once via the popped
per-context receipt) or when recording was never started. See #91283.
Nr.   r³  r¼   r½   r¯   rÉ  ©r-  )rÉ   N)
r   r%   r   r   rE   r?  r@  rO   r   rÓ  )rÉ  r-  r6   r$   rr  s   &&   r   Úfinalize_pending_update_receiptr  e  s´   € ô �l‰l‹n€GØ‚ÙØ%¨Ô2‰yÀYÐRSÄ^¹	Ø!(§¡×!1Ñ!1°-×!@Ò!@‘IÀhð àÒÜ”i× Õ Ü—I’I˜gÓ&ˆEÜŸš w§|¡|Ó4ˆEŒJÜ&)¨)£nˆE�J‰J�{Ñ#Ü�L‰L˜Ô÷	 !ô
 # 7ÔDÐD÷ !× ús   Á-A)C*Ã*C:	c               ó   € V ^8„  d   QhRR/# ©r   r   r¼  r   )r   s   "r   r    r      s   € ÷ ñ ˜>ñ r!   c                 óî  € \         P                  4       p V e.   \        \        V P                  P                  R4      4      4      MRpVf   R# Vw  r#VP                  R4      '       d#    \         P                  V P                  4       V# VP                  RR4       \        P                  ! V 4      pW4n        \         P                  V4       R#   \         d    \         P                  R4        T# i ; i)a•  Carry the open run forward from its own archive when another process took it further.

The completion child resumes this process's snapshot and persists stages (or closes the run)
the snapshot never saw; closing the run from that stale snapshot would erase them. Returns the
archive when the run is already closed there (the open receipt is dropped: nothing is left to
finalize), else None. Never raises.
Nrn   r#   r  )r   r%   rÿ   r9   r   r   rD  rú   r   rÊ  r?  )r6   rf  rþ   rT   rr  s        r   Úresume_run_recordr    sÃ   € ô �l‰l‹n€GØCJÒCVŒOœC §¡× 0Ñ 0°Ó =Ó>Ô?Ð\`€EØ‚}ÙØ�L€DØ‡z�z�-× Ò ð	Ü�N‰N˜7×0Ñ0Ô1ð ˆØ
‡J�Jˆ|˜TÔ"Ü�IŠI�gÓ€EØ„JÜ‡L�L�ÔÙøô ô 	Ü�L‰L˜ÕØˆð	ús   Á*C Ã C4Ã3C4rÉ  c               ó$   € V ^8„  d   QhRRRRRR/# )r   r-  r9   rÉ  rO   r   r¼  r   )r   s   "r   r    r    ™  s'   € ÷ Kñ K°Sð KÈð KÐVdñ Kr!   c               óà  € \        RRR7       \        P                  4       f   R# \        4       pVe   V# \	        \
        4      ;_uu_ 4        \        P                  ! \        P                  4       4      p\        P                  ! VP                  4      Vn        \        V4      VP                  R&   \        P                  V4       RRR4       \        RV R7      #   + '       g   i     L; i)ad  Close a run the operator interrupted AFTER the commit point as ``interrupted``. Never raises.

Not ``failed``: the code already moved, so "still on the previous version" would be false; the
armed obligations finish the rest. The run's own on-disk record is preferred when it is further
along (the completion child persisted stages this process never saw).
u˜   âš  Interrupted after the code was updated: the new code is in place; its remaining steps are owed and the next launch or `hermes update` finishes them.Tr[  NrÉ  r)  r  )r2  r   r%   r  r   rE   r?  r@  r   rO   r   rÓ  )r-  rÉ  Úclosedrr  s   &$  r   Ú#finalize_interrupted_update_receiptr  ™  s¦   € ô 
ð BØIMõOä‡|�|ƒ~ÒÙÜÓ €FØÒØˆÜ	”)×	Õ	Ü—	’	œ(Ÿ,™,›.Ó)ˆÜ—]’] 5§:¡:Ó.ˆŒ
Ü"% i£.ˆ�
‰
�;ÑÜ�‰�UÔ÷	 
ô
 # =¸kÔJÐJ÷ 
×	ús   ÁA;CÃC-	c               ó    € V ^8„  d   QhRRRR/# )r   rã   r   r   r   r   )r   s   "r   r    r    ¯  s   € ÷ ñ  4ð ¨Dñ r!   c           
     ó`  € \        \        4      ;_uu_ 4        R  V P                  R4       4       p\        VR RR7      \        R  F3  p\        \
        4      ;_uu_ 4        VP                  4        RRR4       K5  	  RRR4       R#   + '       g   i     KR  ; i  + '       g   i     R# ; i)c              3  óT   "  € T F  qP                  4       '       g   K  Vx € K   	  R # 5ir;   )Úis_file)r  r³   s   & r   r  Ú&_prune_old_receipts.<locals>.<genexpr>±  s   é € ÐNÑ>˜!Ç)Á)Ç+—A’AÓ>ùó   ‚(ž
(r   c                ó6   € V P                  4       P                  # r;   r"  r%  s   &r   r&  Ú%_prune_old_receipts.<locals>.<lambda>²  s   € °A·F±F³H×4EÒ4Er!   T©rU   ÚreverseN)r   rE   rù   r0  r1  rø   Úunlink)rã   ÚreceiptsÚstales   &  r   rÍ  rÍ  ¯  sz   € Ü	”)×	Õ	ÙN˜yŸ~™~¨oÔ>ÓNˆÜ˜HÑ*EÈtÔTÔUbÐUcÓdˆEÜœ'×"Õ"Ø—‘”÷ #Ñ"ñ e÷ 
Ñ	÷ #×"Ð"ú÷ 
×	Ð	ús$   ˜A	BÁ!BÁ2BÂBÂ	BÂB-	c               ó    € V ^8„  d   QhRRRR/# ©r   rm   rL   r   r,   r   )r   s   "r   r    r    ·  s   € ÷ ñ Ð';ð Ètñ r!   c               óV  €  \        4       R,          p\        P                  ! VP                  RR7      4      p\	        V\
        4      '       g   R# \        V 4      VR&   VP                  R4      p\	        V\
        4      '       g   / pVP                  RRRR	/4       \        4       VR
&   WCR&   V! V4      '       g   R# \        \        P                  ! V^\        R7      R,           P                  R4      4       R#   \         d"   p\        P!                  RT4        Rp?R# Rp?ii ; i)a‡  Record on ``latest.json`` that the fleet it still reports as owed now serves the checkout.

A failed receipt whose plan rows cannot be matched to a live gateway (unknown identity,
pre-pull SHAs) keeps ``hermes update`` exiting 1 and every CLI start warning about mixed
modules, long after the operator's ``hermes gateway restart`` fixed the fleet (#117051). The
caller has just verified every live row is current at the checkout SHA; persisting that
matrix as the receipt's post-restart ``fleet`` (and un-flagging ``gateway_restart``) is what
lets the stale-runtime readers see the recovery. ``discharges(settled_receipt)`` decides on
the in-memory copy; ``latest.json`` is rewritten only when it answers True, so a catch-up
that still owes the restart leaves the receipt byte-identical. Only the ``latest.json`` pointer is
rewritten; the archived per-run file keeps the original outcome. Never raises.
rà   rõ   rö   Frm   rl   r£   r¤   rN   Úsettled_from_live_fleet_atr  r	  r
  Tz>Could not settle latest update receipt from the live fleet: %sN)rÏ   rû   rü   rý   r&   r'   rq   r%   rP   r>   rä   r  r9   r  rE   rB  rC  )rm   Ú
dischargesrþ   rE  rl   rI  s   &$    r   Úsettle_latest_receipt_fleetr0  ·  sò   € ðÜ‹~ Õ-ˆÜ—*’*˜TŸ^™^°[˜^ÓAÓBˆÜ˜'¤4×(Ò(ÙÜ ›;ˆ�ÑØ!Ÿ+™+Ð&7Ó8ˆÜ˜/¬4×0Ò0Ø ˆOØ×Ñ ¨e°]ÀBÐGÔHÜ8D»ˆÐ4Ñ5Ø%4Ð!Ñ"Ù˜'×"Ò"ÙÜ”t—z’z '°!¼SÔAÀDÕH×PÑPÐQXÓYÔZÙøÜô Ü�‰ÐUÐWZÔ[Ýûðús%   ‚AC< ÁA+C< Â><C< Ã<D(ÄD#Ä#D(c               ó   € V ^8„  d   QhRR/# )r   r   r  r   )r   s   "r   r    r    Ù  s   € ÷ ñ Ð5ñ r!   c                 ó¶  € \        \        4      ;_uu_ 4        \        4        U u. uF*  q R,          P                  4       '       g   K!  V R,          NK,  	  pp V'       g    RRR4       R# \	        VR R7      p\
        P                  ! VP                  RR7      4      p\        V\        4      '       d   TMRuuRRR4       # u up i   + '       g   i     R# ; i)z;Read the most recent update receipt, or None. Never raises.rà   Nc                ó6   € V P                  4       P                  # r;   r"  r%  s   &r   r&  Ú%read_latest_receipt.<locals>.<lambda>á  s   € ¨¯©«×):Ò):r!   r(  rõ   rö   )
r   rE   rÖ   r!  Úmaxrû   rü   rý   r&   r'   )ÚdÚpointsrþ   rØ   s       r   r/  r/  Ù  s¡   € ä	”)×	Õ	ô .;¬_Ó^©_¨À]ÕAR×@[Ñ@[×@]Ô#�!�m×#Ð#©_ˆÐ^ßØ÷ 
Ñ	ô �6Ñ:Ô;ˆÜ—*’*˜TŸ^™^°[˜^ÓAÓBˆÜ$ W¬d×3Ò3‰w¸÷ 
Ò	ùò _÷ 
Ö	ñ ús)   ˜C¥CÁCÁCÁ*ACÃCÃC	c               ó    € V ^8„  d   QhRRRR/# )r   rp   r9   r   r  r   )r   s   "r   r    r    ç  s   € ÷ ñ  sð Ð/Gñ r!   c                óL  € \        4       pV'       d   VP                  R4      V 8X  d   V# \        \        4      ;_uu_ 4        R \	        4        4       p\        VR RR7       F�  p\        \        4      ;_uu_ 4        \        P                  ! VP                  RR7      4      p\        V\        4      '       d/   VP                  R4      V 8X  d   VuuRRR4       u uuRRR4       # RRR4       K�  	  RRR4       R#   + '       g   i     K¬  ; i  + '       g   i     R# ; i)	z‡Newest receipt written by the dashboard action ``action_id`` (``latest.json`` first, then
the retained archive), or None. Never raises.rp   c              3  óR   "  € T F  qP                  R 4       F  q"x € K  	  K  	  R# 5i)r   N)rù   )r  r6  r³   s   &  r   r  Ú*read_receipt_for_action.<locals>.<genexpr>î  s    é € ÐP™˜!¿¹¸Ö8O°1”AÑ8O‘A›ùs   ‚%'c                ó6   € V P                  4       P                  # r;   r"  r%  s   &r   r&  Ú)read_receipt_for_action.<locals>.<lambda>ï  s   € °1·6±6³8×3DÒ3Dr!   Tr&  rõ   rö   N)r/  r%   r   rE   rÖ   r0  rû   rü   rý   r&   r'   )rp   r3  Úarchivesrþ   rØ   s   &    r   Úread_receipt_for_actionr?  ç  sÐ   € ô !Ó"€Fß�&—*‘*˜[Ó)¨YÔ6ØˆÜ	”)×	Õ	ÙPœ}œÓPˆÜ˜8Ñ)DÈd×SˆDÜœ)×$Õ$ÜŸ*š* T§^¡^¸[ ^Ó%IÓJ�Ü˜g¤t×,Ò,°·±¸[Ó1IÈYÔ1VØ"÷ %Ó$÷ 
Ò	÷ %Ñ$ñ T÷ 
ñ ÷	 %×$Ð$ú÷ 
Ö	ñ ús+   Á;DÁ=AC>ÃDÃ(DÃ>DÄ		DÄD#	c               ó   € V ^8„  d   QhRR/# )r   r   zlist[tuple[str, Path]]r   )r   s   "r   r    r    ÷  s   € ÷ ñ Ð.ñ r!   c                 ó  a€ ^ RI Hp HpHo . pV ! 4       pVP	                  4       '       d   VP                  RV34       V! 4       pVP	                  4       '       d3   VP                  V3R l\        VP                  4       4       4       4       V# )zT``(profile, home)`` for the default home plus every valid named profile dir, sorted.)Ú_get_default_hermes_homeÚ_get_profiles_rootÚ_PROFILE_ID_REr   c              3  óÜ   <"  € T Fa  pVP                  4       '       g   K  VP                  R 8w  g   K.  SP                  VP                  4      '       g   KQ  VP                  V3x € Kc  	  R# 5i)r   N)Úis_dirr|   rí  )r  rS   rD  s   & €r   r  Ú!_profile_homes.<locals>.<genexpr>  sW   øé € ð 
á/�Ø�|‰|�~ô  à"'§*¡*°	Ñ"9ô  à>L×>RÑ>RÐSX×S]ÑS]×>^ô  ˆU�Z‰Z˜ÕÛ/ùs   ƒA, A,³A,ÁA,)	Úhermes_cli.profilesrB  rC  rD  rF  rQ   Úextendr0  Úiterdir)rB  rC  ÚhomesÚdefault_homerÕ   rD  s        @r   Ú_profile_homesrM  ÷  st   ø€ ç`Ñ`à$&€EÙ+Ó-€LØ×Ñ×ÒØ�‰�i Ð.Ô/ÙÓ€DØ‡{�{‡}‚}Ø�‰ô 
ä §¡£Ô/ó
ô 	
ð
 €Lr!   c               ó    € V ^8„  d   QhRRRR/# )r   Úhomer   r   zOptional[tuple[int, dict]]r   )r   s   "r   r    r    	  s   € ÷ ñ ˜4ð Ð$>ñ r!   c                ó�   €  ^ RI Hp V! V 4      pV'       d   \        VP                  R4      4      V3# R#   \         d     R# i ; i)u  ``(pid, identity)`` declared by the gateway owning ``home``'s control socket, else None.

A live ``identify`` answer is authoritative â€” no PID-reuse or stale-file heuristics. Callers
fall back to ``gateway_state.json`` for gateways that predate the socket or whose socket
didn't bind.
)Úidentify_gatewayrH   N)Úgateway.control_socketrQ  rO   r%   rE   )rO  rQ  Úidentitys   &  r   Ú_socket_identityrT  	  sH   € ðõ 	<á# DÓ)ˆß7?”�H—L‘L Ó'Ó(¨(Ð3ÐIÀTÐIøÜô Úðús   ‚6 ˜6 ´6 ¶AÁAc               ó    € V ^8„  d   QhRRRR/# )r   Úrawr	   r   r¼  r   )r   s   "r   r    r      s   € ÷ ñ ˜Sð  ^ñ r!   c                óÀ  € \        V \        4      '       d	   V '       g   R# \        \        4      ;_uu_ 4        \	        V 4      pVP                  4       '       g    RRR4       R# V.VP                  OR\          FC  pVR,          R,          P                  4       '       g   K)  VP                  4       u uuRRR4       # 	  RRR4       R#   + '       g   i     R# ; i)z?Return the Hermes checkout containing an absolute process path.Nrý  zmain.py)
r&   r9   r   rE   r   Úis_absoluterÞ   Ú_CODE_ROOT_MAX_DEPTHr!  rÔ   )rV  Ú	candidateÚparents   &  r   Ú_code_root_for_pathr\    s¬   € ä�cœ3×Ò§sÙÜ	”)×	Õ	Ü˜“Iˆ	Ø×$Ñ$×&Ò&Ø÷ 
Ñ	ð !Ð5 9×#4Ñ#4Ð5Ð6KÔ7KÓLˆFØ˜Õ%¨	Õ1×:Ñ:×<Ô<Ø—~‘~Ó'Ñ'÷ 
Ò	ñ M÷	 
ñ ÷ 
Ö	ñ ús   ¸#CÁ%:CÂ$CÃ CÃC	c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r    r    ,  s   € ÷ >ñ >˜Nñ >r!   c                 ó`   € \        \        \        \        4      P	                  4       4      4      # r;   )r\  r9   r   Ú__file__rÔ   r   r!   r   Ú_updater_code_rootr`  ,  s   € Üœs¤4¬£>×#9Ñ#9Ó#;Ó<Ó=Ð=r!   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rH   rO   rO  r   r   r¼  r   )r   s   "r   r    r    0  s!   € ÷  ñ  ˜Cð   tð  °ñ  r!   c           	     ó¾  € \        \        4      ;_uu_ 4        ^ RIHp V! VR,          4      ;'       g    / p\	        VP                  R4      4      V 8X  dD   VP                  R4      ;'       g    .  F$  p\        V4      pV'       g   K  Vu uuRRR4       # 	  RRR4       \        \        4      ;_uu_ 4        ^ RIpVP                  V 4      p\        \        4      ;_uu_ 4        \        VP                  4       ;'       g    / P                  R4      4      pV'       d   VuuRRR4       uuRRR4       #  RRR4       . p\        \        4      ;_uu_ 4        VP                  VP                  4       4       RRR4       \        \        4      ;_uu_ 4        TP                  VP                  4       ;'       g    . 4       RRR4       V F$  p\        V4      pV'       g   K  Vu uuRRR4       # 	  RRR4       R#   + '       g   i     ELm; i  + '       g   i     Lâ; i  + '       g   i     L´; i  + '       g   i     L~; i  + '       g   i     R# ; i)zEResolve the checkout served by a verified live gateway when possible.)Úread_runtime_statusúgateway_state.jsonrH   rf   NÚVIRTUAL_ENV)r   rE   Úgateway.statusrc  rO   r%   r\  ÚpsutilÚProcessr[   rQ   ÚexerI  Úcmdline)	rH   rO  rc  rT   ÚproberÕ   rg  ÚprocessÚprobess	   &&       r   Ú_gateway_code_rootrn  0  s£  € ô
 
”)×	Õ	Ý6á$ TÐ,@Õ%@ÓA×GÐGÀRˆÜˆv�z‰z˜%Ó Ó! SÔ(ØŸ™ FÓ+×1Ð1¨rÒ1�Ü*¨5Ó1�ß‘4Ø‘K÷ 
Ò	ñ
 2÷ 
ô 
”)×	Õ	Ûà—.‘. Ó%ˆÜ”i× Õ Ü&¨¯©Ó(9×(?Ð(?¸R×'DÑ'DÀ]Ó'SÓTˆDßØ÷ !Ñ ÷	 
Ò	ð ÷ !ð ˆÜ”i× Õ Ø�M‰M˜'Ÿ+™+›-Ô(÷ !ä”i× Õ Ø�M‰M˜'Ÿ/™/Ó+×1Ð1¨rÔ2÷ !ãˆEÜ& uÓ-ˆDß‰tØ‘÷! 
Ò	ñ ÷ 
ñ" ÷7 
×	Ð	ú÷ !× ú÷
 !× úç × ú÷ 
Ö	ñ" úsŠ   ˜AG>Á/G>Â
G>ÂG>Â9-IÃ&:H	Ä!H	Ä"
IÄ8!IÅ H%	Å9IÆ*H8	ÇIÇ$IÇ2IÇ>H	ÈH"ÈIÈ%H5È0IÈ8IÉIÉI	ÚexternalÚrestart_pendingc               ó    € V ^8„  d   QhRRRR/# )r   rH  r	   r   r,   r   )r   s   "r   r    r    Y  s   € ÷ Hñ H˜ð H ñ Hr!   c                ób   € \        V \        4      ;'       d    V P                  R4      \        8H  # )z@Whether a fleet row serves a checkout this update did not touch.rè  )r&   r'   r%   ÚEXTERNAL_STATE)rH  s   &r   Úrow_is_externalrt  Y  s%   € ä�cœ4Ó ×GÐG S§W¡W¨WÓ%5¼Ñ%GÐGr!   c               óD   € V ^8„  d   QhRRRRRRRRRRR	RR
RRRRRRRRR/# )r   r°   r9   rH   rO   Úcode_shar	   Úcode_versionÚexpected_sharè  Ú	code_rootr¼  Úexpected_rootÚserved_profilesÚself_restart_pendingúOptional[set]r   rA   r   )r   s   "r   r    r    ^  sl   € ÷ ñ ØðØðØ&)ðØ9<ðØLOðàðà'5ðð "ðð <?ðð (ð	ð
 ñr!   c
                óD  € VR 8X  d   V'       d   V'       d   Wg8w  d   \         pVR 8X  d.   V'       d&   V'       d   \        V4      \        V4      8X  d   RMRpVR8X  d   V	'       d   W9   d   \        pRT RTRV'       d   \        V4      MRRTRTR	V'       d   \        V4      MR/p
\        V\        4      '       dd   V'       d\   \
        ;QJ d    R
 V 4       F  '       d   K   RM	  RM! R
 V 4       4      '       d"   \	        \        P                  V4      4      V
R&   V
# )Úunknownr6   r*  r°   rH   rv  Nrw  rè  ry  c              3  óV   "  € T F  p\        V\        4      ;'       d    Tx € K!  	  R # 5ir;   )r&   r9   )r  r|   s   & r   r  Ú_fleet_row.<locals>.<genexpr>s  s&   é € ð EÙ3B¨4Œ
�4œÓ×&Ð& $Ô&³?ùs   ‚)ž)FTr{  )rs  r9   ÚRESTART_PENDING_STATEr&   rq   Úallr'   Úfromkeys)r°   rH   rv  rw  rx  rè  ry  rz  r{  r|  rH  s   &&&&&&&&&& r   Ú
_fleet_rowr…  ^  sê   € ð �	ÔŸi¯M¸iÔ>XÜˆØ�	ÔŸh¯<Ü  ›]¬c°,Ó.?Ô?‘	ÀWˆØ�Ô×0°SÔ5PÜ%ˆà�7˜E 3¨
ÇX´C¸´MÐSWØ˜ g¨uØ§y”S˜”^°dð€Cô �/¤4×(Ò(¯_ÇÃñ EÙ3BóEÇÇÂñ EÙ3BóE÷ Bò Bô "&¤d§m¡m°OÓ&DÓ!EˆÐÑØ€Jr!   ÚstoppedÚstartup_failedÚpre_restart_pidsr|  c               ó$   € V ^8„  d   QhRRRRRR/# )r   rˆ  zOptional[list[int]]r|  r}  r   rL   r   )r   s   "r   r    r    ~  s)   € ÷ Zñ ZØ,ðZØKXðZàñZr!   c                óš  € T ;'       g    .  Uu0 uF&  p\        V\        4      '       g   K  \        V4      kK(  	  ppT;'       g    R Uu0 uF&  p\        V\        4      '       g   K  \        V4      kK(  	  pp. p\        RR7      P                  R4      p\	        4       p ^ RIHpHp	Hp
 \        4        EF¿  w  r¼\        V4      pVeg   Vw  rï\        W¾VP                  R4      VP                  R4      VVP                  R4      \        Wì4      VVR	7	      pVP                  / VCR
R/C4       K{  V	! VR,          4      pV'       g   K”   \        VP                  R4      4      pT! T4      T8X  d\   TP                  \        Y¾TP                  R4      TP                  R4      TTP                  R4      \        Yì4      TTR	7	      4       EK  T
! T4      '       d!   TP                  \        Y¾RRR4      4       EKE  TP                  R4      pYã9   g   EK_  \        T\         4      '       g   EKx  T'       g   EKƒ  T\"        9  g   EK‘  TP                  \        Y¾RTP                  R4      RRR7      4       EKÂ  	  V# u upi u upi   \        \        3 d     EKå  i ; i  \$         d"   p\&        P)                  RT4        Rp?T# Rp?ii ; i)u©  Snapshot every profile's gateway code identity vs. the current tree.

``self_restart_pending`` â€” pids of gateways that are ancestors of this updater and accepted a
self-restart request (cron update inside the gateway tree, #100179). They can only restart after
this process exits, so their pre-update ``code_sha`` is expected: such a row is
``restart_pending`` instead of ``stale`` and does not fail the matrix (#119597). Every other
live gateway on the old sha keeps its ``stale`` verdict.

Rollout safety: ``down`` requires membership in ``pre_restart_pids`` â€” a stale state file from a
long-dead gateway (machine reboot, manual kill weeks ago) must NOT fail every future update.
Without a pre-restart snapshot (``None``/empty) dead PIDs are skipped (historical behavior).

``stale``   â€” gateway stamped a code_sha that differs from the updated checkout's HEAD (it is still
serving pre-update modules). ``unknown`` â€” gateway predates the code-identity stamp (started before this
feature landed), identity could not be resolved, or the state file's live PID is not the
verified gateway for that home (``live_gateway_pid_for_home``): ``write_runtime_status`` re-stamps
``pid``/``code_sha`` for whatever process writes it, so a foreign writer must never read as
``current`` (#110420, sibling of #109680). ``down``    â€” the gateway was ALIVE when this update
started (``pre_restart_pids``), its runtime status still says running, but the PID is dead and no
successor rewrote the record: the restart phase stopped it and nothing came back. Without this row a
killed-and-never-replaced gateway produced NO entry at all and the matrix passed silently (Phase-1
verification gap, #88848/#74973 class).
TrD   r  )Úlive_gateway_pid_for_homerc  Úruntime_status_pid_is_liveNrv  rw  r{  )r{  ry  rz  r|  ÚsourceÚsocketrd  rH   Úgateway_stateÚdown)rè  zFleet version probe failed: %sr   )r&   rO   rG   r%   r`  rf  r‹  rc  rŒ  rM  rT  r…  rn  rQ   Ú	TypeErrorrú   r9   Ú_NOT_EXPECTED_STATESrE   rB  rC  )rˆ  r|  r³   Ú_pre_restartÚ_pendingÚresultsrx  rz  r‹  rc  rŒ  r°   rO  ÚsockrH   rS  rH  rT   Úgw_staterI  s   $$                  r   Úcollect_fleet_versionsr˜  ~  sv  € ð4 &6×%;Ð%;¸Ð%;ÓSÑ%;˜qÄ
È1Ìc×@R”F”C˜–FÑ%;€LÐSØ!5×!;Ð!;¸Ð!;ÓSÑ!;˜1Ä
È1Ìc×@R””�A–Ñ!;€HÐSØ$&€GÜ!¨$Ô/×3Ñ3°EÓ:€LÜ&Ó(€Mð:<÷	
ñ 	
ô ,×-‰MˆGÜ# DÓ)ˆDØÒØ $‘�Ü Ø (§,¡,¨zÓ":¸H¿L¹LÈÓ<XÐZfØ$,§L¡LÐ1BÓ$CÜ0°Ó;È=Ø)1ô	�ð —‘Ð: #Ð: x°Ñ:Ô;ÙÙ(¨Ð0DÕ)DÓEˆFßÙðÜ˜&Ÿ*™* UÓ+Ó,�ñ )¨Ó.°#Ô5Ø—‘ÜØ f§j¡j°Ó&<¸f¿j¹jÈÓ>XÐZfØ(.¯
©
Ð3DÓ(EÜ"4°SÓ"?È}Ø-5ô	ôò ñ
 *¨&×1Ò1Ø—‘œz¨'¸¸dÀDÓIÔJÚð —z‘z /Ó2ˆHØ×"¤z°(¼C×'@Õ'@ÇXÂXÐRZÔbv×RvØ—‘œz¨'¸¸f¿j¹jÈÓ>XÐZ^ÐflÔm×nñc .ðh €NùòA TùÚSøô8 œzÐ*ô ÛðûôB ô <Ü�‰Ð5°s×;Ð;Ø€Nûð<úsx   �I;¬I;ÁJ Á(J Â!B%J ÅJ Å
JÅ$A5J Ç4J ÈJ È-J È8J É3J ÊJÊJ ÊJÊJ ÊK
Ê)KËK
r6   u4     âœ“ {profile} (pid {pid}) @ {short} â€” up to dater*  uA     âœ— {profile} (pid {pid}) @ {short} â€” STALE (pre-update code)r�  uk     âœ— {profile} â€” DOWN (gateway was running before the update; pid {pid} is gone and nothing replaced it)uT     â—† {profile} (pid {pid}) @ {short} â€” separate checkout, not updated by this runu‚     â†» {profile} (pid {pid}) @ {short} â€” restart pending (deferred until this process exits; the update runs inside this gateway)ud     ? {profile} (pid {pid}) â€” version unknown (gateway predates version stamping; restart to enable)u�     ? {profile} (pid {pid}) â€” new pid since the update, code identity not published yet â€” re-check with `hermes gateway status`c               ó    € V ^8„  d   QhRRRR/# r,  r   )r   s   "r   r    r    ð  s   € ÷ 0ñ 0Ð&:ð 0¸tñ 0r!   c                óŽ  € V '       g   R# \        4        \        R4       \        4       p. pV  EF9  pVP                  R4      pVP                  VP                  R4      4       \	        V4      '       dL   VP                  R4      '       d5   VP                  VP                  R4       RVP                  R4       24       VP                  R4      '       d   \        M\        p\        \        P                  VP                  R4      V4      P                  VP                  R4      VP                  R	4      \        V\        4      '       d   V'       d
   VR
,          MRR7      4       EK<  	  V'       d-   \        4        \        R4       V F  p\        RV 24       K  	  \        V9   d!   \        4        \        R4       \        R4       \        R V  4       4      pV'       d^   \        4        RV9   d   \        R4       RV9   d   \        R4       \        4        \        RV R24       \        R4       \        R4       V^ 8„  # )aG  Print the post-update fleet version matrix.

Returns True when at least one gateway is provably stale (still serving pre-update code) OR
provably down (killed by the restart phase, nothing came back), so the caller can escalate.
``unknown`` entries are reported but do NOT fail the update: gateways started before the
code-identity stamp existed have no sha to compare, and failing them would be a false-positive
storm. ``restart_pending`` entries (the gateway this updater runs inside, self-restart
accepted) are on the old code by construction and do not fail it either (#119597).
FzFleet version check:rv  rè  ry  r°   z: Úidentity_pendingrH   ré   Ú?)r°   rH   ÚshortuG     â„¹ These profiles run their own checkout and are updated separately:z      uJ     â„¹ A restart-pending gateway has not yet been verified on the new code;z?    check after this update exits with `hermes gateway status`.c              3  óT   "  € T F  qP                  R 4      R9   g   K  ^x € K   	  R# 5i)rè  N)r*  r�  rä  )r  rS   s   & r   r  Ú-print_fleet_version_matrix.<locals>.<genexpr>  s!   é € ÐX¡u˜e·	±	¸'Ó0BÐFWÑ0WŸš£uùr#  r*  uB     âš  Stale gateways keep serving pre-update code until restarted.r�  u7     âš  Down gateways stopped serving messaging entirely.u    âš  Gateway restart still owed: z4 gateway(s) still running the old code (or stopped).zT  Run `hermes gateway restart` (or `hermes -p <profile> gateway restart` for a namedz4  profile), then `hermes gateway status` to confirm.)r2  r   r%   Úaddrt  rQ   Ú_FLEET_ROW_IDENTITY_PENDINGÚ_FLEET_ROW_UNKNOWNÚ_FLEET_ROW_LINESr   r&   r9   r‚  Úsum)rm   ÚstatesÚexternal_rootsrS   r  ÚfallbackÚlineÚstale_or_downs   &       r   Úprint_fleet_version_matrixrª  ð  sÑ  € ÷ ÙÜ	„GÜ	Ð
 Ô!Ü‹U€FØ "€NÜˆØ�i‰i˜
Ó#ˆØ�
‰
�5—9‘9˜WÓ%Ô&Ü˜5×!Ò! e§i¡i°×&<Ò&<Ø×!Ñ! U§Y¡Y¨yÓ%9Ð$:¸"¸U¿Y¹YÀ{Ó=SÐ<TÐ"UÔVØ27·)±)Ð<N×2OÒ2OÕ.ÔUgˆÜÔ×"Ñ" 5§9¡9¨WÓ#5°xÓ@×GÑGØ—I‘I˜iÓ(¨e¯i©i¸Ó.>ÔQ[Ð\_Ôad×QeÒQe×jmÀcÈ"ÆgÐsvð Hó 
÷ 	ñ ÷ ÜŒÜÐWÔXÛ"ˆDÜ�F˜4˜&�/Ö"ñ #ä Ô&ÜŒÜÐZÔ[ÜÐOÔPÜÑX¡uÓXÓX€MßÜŒØ�fÔÜÐVÔWØ�VÔÜÐKÔLô 	ŒÜØ.¨}¨oÐ=qÐrô	täÐdÔeÜÐDÔEØ˜1ÑÐr!   )F>   rP  Ú	launchersÚ
completionÚmaintenanceÚdependenciesÚprofile_syncÚconfig_migration>   rP  r«  r¬  rÀ   r;   )NrN   )r  NNNN)lÚ__conditional_annotations__rÅ   Ú
__future__r   Úcontextvarsr?  rû   ÚloggingrZ   rí   rŠ  rr   rï   rt   Ú
contextlibr   r   r   r   r   Úpathlibr   Útypingr	   r
   Ú	getLoggerrÁ   rB  r1  r   Ú__annotations__ÚCOMMAND_BOUNDARY_STOP_REASONÚ
ContextVarr   r   r   r)   r/   r7   r>   rG   rV   r]   r_   rÏ   rÖ   rä   rò   rÿ   r  r  r5  rJ  rM  Ú	frozensetÚTAIL_FOLLOWUPSrR  rU  r`  rc  rg  rj  r_  rv  ry  rT  r~  r�  r…  Úcompiler¡  r”  r‘  r°  rº  rÓ  rà  rì  rî  rø  rþ  r  r	  rÎ  r  r  r  r  rÍ  r0  r/  r?  rM  rT  rY  r\  r`  rn  rs  r‚  rt  r…  r’  r˜  r£  r¢  r¡  rª  )r±  s   @r   Ú<module>r¿     sñ  øðôõ: #ã Û Û Û Û 	Û 	Û Û 
Û Û ß /ß ,Ñ ,Ý ß  à	×	Ò	˜8Ó	$€à€à(*€
Ð%Ó *Ø>Ð ð =H×<RÒ<RØ dô=€Ð
9ó ð
 EP×DZÒDZØ#¨TôE€ÐAó ð
 ñó ðõ.õVõ	Cõ)÷ð	ÀU÷ 	õN÷R@ñ R@õjBõNõ:õwõõ"õ,;õ ðB%#°Dð %#ÐW[÷ %#õP'ñ ò >ó ?€ñ Ò@ÓA€õlð
'Ð<k÷ 'õ(õ#õ 9õ;÷,=õ
9õ
õ6õ
Jõ
Cð —z’zÐ"IÓJÐ õ
?÷õ"Oõ6$÷<[õ|Fð( —z’zðPóQÐ ð —J’JÐ6Ó7Ð õ&õRõõ$võ"$õ.=÷Eõ4ð4KÈc÷ Kõ,õõDõõ õ$ð$ Ð õõ>õ ðF €ð *Ð õH÷
ð: "Ð#3Ð4Ð ðZØ/3ðZØ[_÷Zð| ÐEØÐPØ
ÐyØÐfØð	0ð	Ð ð |Ð ð1ð ÷0r!   