+
    „WÝj˜z  ã                   ó2  a € RB t20 t R t^ RIt^ RIt^ RIt^ RIHtHtHtHt ^ RI	H
t
 ^ RIHt ^ RIHt ]P                  ! R4      tRt^tRtRs] ^ k R	 R
 ltR R ltR R ltR R ltRCR R lltR R ltRR/R R lltR R ltR R ltR R ltR R ltR  R! lt RCR"R#/R$ R% lllt!RDR& R' llt"R( R) lt#R* R+ lt$R, R- lt%R. R/ lt&R0 R1 lt'](! 0 REm4      t)R2 R3 lt*RR/R4 R5 llt+R6 R7 lt,RDR8 R9 llt-R: R; lt.R< R= lt/RFRR/R> R? lllt0R@ RA lt1R# )Ga\  Autostash handling for ``hermes update``: stash before the pull, restore/park/discard afterwards, warn about orphans.

Split out of ``update_cmd.py``; names are re-imported there so ``hermes_cli.update_cmd.<name>`` still resolves/monkeypatches.
Origin helpers are imported lazily per function (no cycle; test patches on the origin stay effective).
N)ÚdatetimeÚ	timedeltaÚtimezoneÚUTC)ÚPath)ÚOptional)Ú_record_stopzhermes_cli.update_cmdzhermes-update-autostash-zT  The stash was left in place. You can remove it manually after checking the result.c                óh   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        /# ©é   Úgit_cmdÚargsÚcwd©ÚlistÚstrr   )Úformats   "ÚOC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\update_cmd_stash.pyÚ__annotate__r   &   s)   € ÷ ñ œœS�	ð ¬¬c­ð ¼ñ ó    c                ón   € ^ RI Hp  V! W3RVRR/VB #   \        \        P                  3 d     R# i ; i)zS``subprocess.run`` of a git command with captured output; None when git cannot run.©Úrun_gitr   Úcapture_outputTN)Úhermes_cli.update_custodyr   ÚOSErrorÚ
subprocessÚSubprocessError)r   r   r   Úkwargsr   s   &&&, r   Ú
_git_quietr   &   sA   € å1ðÙ�wÑM¨#ÐM¸dÐMÀfÑMÐMøÜ”Z×/Ñ/Ð0ô Úðús   ˆ •4³4c                óJ   € V ^8„  d   QhR\         R\        \         R3,          /# )r   Úporcelain_zÚreturn.)r   Útuple)r   s   "r   r   r   0   s"   € ÷ ñ ¤cð ¬e´C¸°H­oñ r   c                ó–   € \         ;QJ d#    . R V P                  R4       4       F  NK  	  5# ! R V P                  R4       4       4      # )ag  Paths recorded with ``git add -N`` (intent-to-add), read from NUL-separated porcelain output.

Such an entry carries the empty blob with zeroed stat data, so it is never "uptodate" and
``git stash push`` rejects the whole stash with ``Entry 'X' not uptodate. Cannot merge.`` - a dead
end for the user, because that is the state an editor leaves behind when it shows a new file in
diffs. Porcelain marks it ``" A"`` (in the worktree, absent from the index); a real staged add is
``"A "`` and an untracked file ``"??"``. Rename records carry a second, prefix-less field, which
the leading ``" A"`` test cannot match.
c              3   ó˜   "  € T F@  p\        V4      ^8”  g   K  V^ ,          R8X  g   K%  V^,          R8X  g   K5  VR,          x € KB  	  R# 5i)é   Ú ÚA:r&   NNN)Úlen)Ú.0Úrecords   & r   Ú	<genexpr>Ú'_intent_to_add_paths.<locals>.<genexpr>:   sL   é € ð Ù!8�vÜˆv‹;˜‰?ô 	Ø% a�y¨CÑ/ô 	Ø4:¸1µIÀÑ4Dô 	ˆˆr�
Š
Ó!8ùs   ‚A
™A
©A
¹A
Ú )r#   Úsplit)r!   s   &r   Ú_intent_to_add_pathsr0   0   sL   € ÷ Œ5ñ Ø!,×!2Ñ!2°4Ô!8ó�5ð ˆ5ñ Ø!,×!2Ñ!2°4Ô!8óó ð r   c                óh   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        /# r
   r   )r   s   "r   r   r   @   s.   € ÷ @ñ @œ$œs�)ð @¬4´­9ð @¼4ñ @r   c           	     óÂ   € \        WVRRRR7      pVe   VP                  ^ 8w  d   R# VP                  P                  R4       Uu0 uF  qD'       g   K  VkK  	  up# u upi )zcNUL-separated path listing as a set, or None when git failed (surrogateescape keeps odd filenames).Tzutf-8Úsurrogateescape)ÚtextÚencodingÚerrorsNr.   )r   Ú
returncodeÚstdoutr/   )r   r   r   ÚresultÚpaths   &&&  r   Ú_git_paths_zr;   @   sW   € ä˜ s°ÀÐPaÔb€FØ‚~˜×*Ñ*¨aÔ/ÙØ#Ÿ]™]×0Ñ0°Ô6Ó?Ñ6�T»$�DˆDÑ6Ñ?Ð?ùÒ?s   Á	AÁAc                óJ   € V ^8„  d   QhR\         \        ,          R\        RR/# ©r   r   r   r"   Nr   )r   s   "r   r   r   H   s*   € ÷ Pñ Pœœc�ð P¬ð P°$ñ Pr   c                 ó.   € ^ RI Hp V! V . ROVRR7       R# )é    r   T)r   r   N©Úresetz--hardÚHEAD)r   r   )r   r   r   s   && r   Ú_reset_hardrC   H   s   € Ý1áˆGÒ0°cÈ$×Or   c                ó4   € V ^8„  d   QhR\         R\         RR/# )r   r4   Úprefixr"   N©r   )r   s   "r   r   r   N   s!   € ÷ )ñ )œ#ð )¤sð )°Dñ )r   c                 óp   € V P                  4       '       d    \        V V P                  4        24       R # R # ©N)ÚstripÚprint)r4   rE   s   &&r   Ú_print_nonemptyrK   N   s)   € Ø‡z�z‡|‚|Ü��˜Ÿ™›˜Ð'Ö(ñ r   c                ó(   € V ^8„  d   QhR\         RR/# )r   r4   r"   NrF   )r   s   "r   r   r   S   s   € ÷ 3ñ 3œCð 3 Dñ 3r   c                 ó˜   € V P                  4       '       d4   \        R V P                  4       P                  4       ^ ,           24       R# R# )z  N)rI   rJ   Ú
splitlines)r4   s   &r   Ú_print_first_linerO   S   s6   € Ø‡z�z‡|‚|Ü��4—:‘:“<×*Ñ*Ó,¨QÕ/Ð0Ð1Ö2ñ r   Úcheckout_movec                óh   € V ^8„  d   QhR\         \        ,          R\        R\        \        ,          /# ©r   r   r   r"   ©r   r   r   r   )r   s   "r   r   r   X   s,   € ÷ !ñ !¬D´­Ið !¼Dð !Ô\dÔehÕ\iñ !r   c               óž  € ^ RI HpHp RsV! V . ROVRR7      pVP                  P                  4       '       g   R# V! V RR.V4      P                  P                  4       '       d   \        R4       \        V R.V4       \        VP                  4      pV'       dM   \        R	\        V4       R
24       V! V RR.VOV4      pVP                  ^ 8w  d   \        VP                  4       \        P                  ! \        4      P!                  \"         R24      p\        R4       V! V . ROV4      P                  P                  4       p	T;'       g    T! RR7      ;_uu_ 4        \%        WW‰4      p
RRR4       X
\        VP                  P'                  R4       Uu. uF  q»'       g   K  VNK  	  up4      3sV
#   + '       g   i     LQ; iu upi )z»Stash local changes before the update moves the checkout; the stash commit, or None when clean.
``checkout_move`` binds the push (and its cleanup reset) to the paused gateways' tree gate.)Ú_git_runÚ_no_moveNT©Úcheckúls-filesz
--unmergedu?   â†’ Clearing unmerged index entries from a previous conflict...rA   u   â†’ Making z# intent-to-add file(s) stashable...Úaddú--ú%Y%m%d-%H%M%Su8   â†’ Local changes detected â€” stashing before update...©Úrevertr.   )Ústatusz--porcelainú-z©ú	rev-parseú--verifyz
refs/stash)Úhermes_cli.update_cmd_gitrU   rV   Ú_pending_autostashr8   rI   rJ   r   r0   r)   r7   rK   Ústderrr   Únowr   ÚstrftimeÚ_AUTOSTASH_NAME_PREFIXÚ_push_stashr/   )r   r   rP   rU   rV   r_   Úintent_to_addrZ   Ú
stash_nameÚ
prev_stashÚ	stash_refÚentrys   &&$         r   Ú_stash_local_changes_if_neededrp   X   sˆ  € ÷ =ØÐÙ�gÒ>ÀÈ4ÔP€FØ�=‰=×Ñ× Ò Ùñ �˜* lÐ3°SÓ9×@Ñ@×FÑF×HÒHÜÐOÔPÜ�7˜W˜I sÔ+ô )¨¯©Ó7€MßÜ�œC Ó.Ð/Ð/RÐSÔTÙ�w ¨Ð =¨}Ð =¸sÓCˆØ�>‰>˜QÔÜ˜CŸJ™JÔ'ä—’œcÓ"×+Ñ+Ô/EÐ.FÀmÐ,TÓU€JÜ	Ð
DÔEÙ˜'Ò#JÈCÓP×WÑW×]Ñ]Ó_€JØ
×
#Ð
#˜8Ð
#¨D×	1Ö	1Ü ¨jÓEˆ	÷ 
2ð 	”3¨6¯=©=×+>Ñ+>¸tÔ+DÓNÑ+D %ËŸ˜Ñ+DÑNÓOðQÐàÐ÷	 
2×	1üò Os   Å!F7Æ	G

Æ'G

Æ7G	c          
      ój   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\        /# )r   r   r   rl   rm   r"   r   )r   s   "r   r   r   |   s4   € ÷ ñ œœc�ð ¬ð ¼3ð ÌCð ÔTWñ r   c                ó¦  € ^ RI Hp V! V RRRRV.V4      p\        VP                  4       V! V . ROV4      pVP                  P	                  4       pVP
                  ^ 8H  ;'       d    \        V4      ;'       d    Ws8g  pVP
                  ^ 8w  dÂ   V'       g„   \        R4       \        VP                  4       \        R4       \        R4       \        R	4       \        P                  ! VP
                  VP                  VP                  VP                  R
7      h\        VP                  4       \        R4       \        R4       \        W4       V# )z’``git stash push``; the stash commit. Raises when nothing was saved; resets tracked leftovers
when a push saved everything but could not clean up.©rU   ÚstashÚpushz--include-untrackedz-mu5   âœ— Could not stash local changes â€” update aborted.zV  Commit, stash, or clean up your local changes manually, then re-run `hermes update`.zS  (An index entry from `git add -N` is the usual cause of this error; `git add` thezE   paths it names, or `git reset` them, and the update will proceed.))Úoutputrf   uZ     âš  Some untracked files could not be removed from the working tree (permission denied).u[       They were still saved to the stash and were left in place â€” the update will continue.ra   )rd   rU   rK   r8   rI   r7   ÚboolrJ   rO   rf   r   ÚCalledProcessErrorr   rC   )	r   r   rl   rm   rU   ru   Ústash_probern   Ústash_createds	   &&&&     r   rj   rj   |   s  € õ 3Ù�G˜g vÐ/DÀdÈJÐWÐY\Ó]€DÜ�D—K‘KÔ Ù˜7Ò$KÈSÓQ€KØ×"Ñ"×(Ñ(Ó*€IØ×*Ñ*¨aÑ/×_Ð_´D¸³O×_Ð_È	ÑH_€MØ‡�˜!ÔßäÐIÔJÜ˜dŸk™kÔ*ÜÐjÔkÜÐgÔhÜÐYÔZÜ×/Ò/°·±ÀÇÁÐSW×S^ÑS^Ðgk×grÑgrÔsÐsô 	˜Ÿ™Ô$ÜÐjÔkÜÐkÔlô 	�GÔ!ØÐr   c          	      ót   € V ^8„  d   QhR\         \        ,          R\        R\        R\        \        ,          /# ©r   r   r   rn   r"   rS   )r   s   "r   r   r   ™   s1   € ÷ ñ ¤T¬#¥Yð ´Tð Äcð ÌhÔWZÍmñ r   c                óf  € ^ RI Hp V! V . ROVRR7      pVP                  P                  4        F~  pVP	                  R4      w  rgpVP                  4       V8X  g   K.  \        P                  ! RVP                  4       4      p	V	'       d   V	P                  ^4      u # VP                  4       u # 	  R# )a2  Selector for the stash entry whose commit is *stash_ref*, as the bare index ``N``
(git accepts it wherever ``stash@{N}`` is valid). Never ``stash@{N}`` itself: on native
Windows the MSYS runtime strips the braces from git.exe's argv, so ``stash@{0}`` reaches git
as ``stash@0`` and the drop fails (#87542).rs   TrW   r'   zstash@\{(\d+)\}N)rt   r   z--format=%gd %H)	rd   rU   r8   rN   Ú	partitionrI   ÚreÚ	fullmatchÚgroup)
r   r   rn   rU   Ú
stash_listÚlineÚselectorÚ_ÚcommitÚmatchs
   &&&       r   Ú_resolve_stash_selectorrˆ   ™   sŒ   € õ
 3Ù˜'Ò#GÈÐTXÔY€JØ×!Ñ!×,Ñ,Ö.ˆØ"Ÿn™n¨SÓ1Ñˆ�VØ�<‰<‹>˜YÖ&Ü—L’LÐ!3°X·^±^Ó5EÓFˆEß%*�5—;‘;˜q“>Ò@°·±Ó0@Ò@ñ	 /ñ
 r   c                ó   € V ^8„  d   QhRR/# )r   r"   N© )r   s   "r   r   r   ¨   s   € ÷ ñ  $ñ r   c                 ó
   € Rs R# )zNForget this run's unsettled autostash after it was already reported (#122557).N©re   rŠ   r   r   Ú_clear_pending_autostashr�   ¨   s
   € ð Òr   c                ó:   € V ^8„  d   QhR\         \        ,          /# ©r   r"   )r   r   )r   s   "r   r   r   ®   s   € ÷ Rñ R¤h¬s¥mñ Rr   c            	     óD   € \         f   R# \         w  rRV RV  RV  RV  R2	# )a  What to tell the user while this run's autostash is unsettled (#122557), else ``None``.

Used as the completion line (it is not a success line, so the update ends partial and
exits non-zero) and printed by failure verdicts, which otherwise never name the stash.
Nu   âš  hermes update stashed z> local modification(s) and did NOT restore them.
  Stash ref: z&
  Review with: git stash show --stat z$
  Re-apply with: git stash show -p z | git apply --3wayrŒ   )rn   Ú
file_counts     r   Ú_unrestored_autostash_noticer’   ®   sI   € ô Ò!ÙÜ.Ñ€IØ(¨¨ð 5Ø%˜;ð '4Ø4=°;ð ?2Ø2;°Ð<OðQð Rr   c                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# rR   )r   r   r   Úint)r   s   "r   r   r   ½   s%   € ÷ .ñ .¬t´C­yð .¼tð .Ìñ .r   c           	     óî  € ^ RI Hp  V! V . ROV4      pVP                  ^ 8w  d   ^ # \        P                  ! \
        4      \        \        R7      ,
          p. pVP                  P                  4        F¨  pVP                  4       P                  R4      w  rxp	V	P                  \        4      p
V
^ 8  d   KC  Wš\        \        4      ,           R R,          p \        P                  ! VR4      P!                  \
        R7      pYÄ8  g   K–  TP%                  Y{34       Kª  	  V'       g   ^ # \'        4        \'        R\        V4       R	\        V4      ^8X  d   R
MR R\         R24       V F  w  r{\'        RV R\         V R24       K  	  \'        R4       \'        R4       \'        R4       \        V4      #   \"         d     EKR  i ; i  \(         d"   p\*        P-                  RT4        Rp?^ # Rp?ii ; i)uŒ  Print a notice for update autostashes older than the warn threshold; return the count (0 on any git failure).

Autostashes legitimately outlive a run (--keep-stash, failed restore) but nothing re-surfaces them.
Deliberately NOT a GC: a stash may be the only copy of the user's work, so Hermes never drops one.

Autostash entries legitimately outlive an update run (``--keep-stash`` parks them; a conflicted or
failed restore preserves them for safety), but nothing ever re-surfaces them afterwards â€” they sit in
``git stash`` invisibly for weeks (#63717 problem 6). This prints a short notice naming the stale
entries with recovery/cleanup guidance.
rs   )Údaysr'   N:Né   Nr\   )Útzinfou   âš  z leftover update autostash entrzy iszies arez more than z
 days old:ú    z  (Ú)z?  These hold local changes stashed by earlier updates and neverz2  restored. Review with: git stash show -p <entry>zN  Restore with: git stash apply <entry>   Discard with: git stash drop <entry>zAutostash age check failed: %s)rt   r   z--format=%gd %s)rd   rU   r7   r   rg   r   r   Ú_AUTOSTASH_WARN_AGE_DAYSr8   rN   rI   r~   Úfindri   r)   ÚstrptimeÚreplaceÚ
ValueErrorÚappendrJ   Ú	ExceptionÚloggerÚdebug)r   r   rU   r‚   ÚcutoffÚstalerƒ   r„   r…   ÚsubjectÚposÚstampÚ
stash_timeÚexcs   &&            r   Ú!_warn_orphaned_update_autostashesr«   ½   sº  € õ 3ð"Ù˜gÒ'KÈSÓQˆ
Ø× Ñ  AÔ%ÙÜ—’œcÓ"¤YÔ4LÔ%MÕMˆØ')ˆØ×%Ñ%×0Ñ0Ö2ˆDØ#'§:¡:£<×#9Ñ#9¸#Ó#>Ñ ˆH˜Ø—,‘,Ô5Ó6ˆCØ�QŒwÙØ¤#Ô&<Ó"=Õ=Ð>Ð?ÀÕDˆEðÜ%×.Ò.¨u°oÓF×NÑNÔVYÐNÓZ�
ð Ö"Ø—‘˜hÐ.Ö/ñ 3÷ ÙÜŒÜØ”3�u“:�,Ð=Ü˜U› qœ‰v¨iÐ8¸Ü'Ð(¨
ð4ô	
ó
  %‰OˆHÜ�D˜˜
 #Ô&<Ð%=¸e¸WÀAÐFÖGñ  %äÐOÔPÜÐBÔCÜÐ^Ô_Ü�5‹zÐøô# ô Ûðûô$ ô Ü�‰Ð5°sÔ;ÝûðúsN   ˆG §B-G Ã+F5Ä G ÄG Ä(BG Æ5GÇ G ÇGÇG ÇG4ÇG/Ç/G4ÚchosenFc          
      óL   € V ^8„  d   QhR\         R\         R\         R\        RR/# )r   Úoutcomern   Údetailr¬   r"   N©r   rw   )r   s   "r   r   r   î   s1   € ÷ ñ ¤sð ´sð ÄCð ÔY]ð Ðjnñ r   c               ó‚   € V R8w  g	   V'       d   Rs ^ RIHp T! RV R8g  V  RV 2V'       d   RV R2MR,           4       R# )	aJ  Note the autostash disposition in the update receipt so a parked stash is visible
to automation reading receipts instead of stdout (#115363: an update that ended with
local changes parked in the stash reported a bare success with no trace of them).
A park the user did not ask for (``chosen``) keeps the stash unsettled (#122557).ÚparkedN)Úrecord_stepÚlocal_changes_stashz: z (rš   Ú )re   Úhermes_cli.update_receiptr³   )r®   rn   r¯   r¬   r³   s   &&&$ r   Ú_record_stash_dispositionr·   î   sI   € ð �(ÔŸfØ!ÐÝ5ÙØØ�8ÑØˆ)�2�i�[Ð!·v r¨&¨°¡^À2ÕFör   c                óJ   € V ^8„  d   QhR\         R\        \         ,          RR/# )r   rn   Ústash_selectorr"   N)r   r   )r   s   "r   r   r   þ   s+   € ÷ `ñ `¬Sð `Ä(Ì3Å-ð `Ð[_ñ `r   c                 ó€   € \        R 4       \        R4       V'       d   \        RV 24       R# \        RV  R24       R# )zS  Check `git status` first so you don't accidentally reapply the same change twice.z@  Find the saved entry with: git stash list --format='%gd %H %s'z!  Remove it with: git stash drop z  Look for commit z0, then drop it by index with: git stash drop <N>N)rJ   )rn   r¹   s   &&r   Ú_print_stash_cleanup_guidancer»   þ   s;   € Ü	Ð
_Ô`Ü	Ð
LÔMßÜÐ1°.Ð1AÐBÖCäÐ" 9 +Ð-]Ð^Ö_r   c                ó0   € V ^8„  d   QhR\         R\        /# )r   rf   r"   r°   )r   s   "r   r   r     s   € ÷ ñ ¼3ð Ä4ñ r   c                ó²   € RpR T ;'       g    RP                  4        4        F/  pRV9   g   RV9   d   RpK  VP                  R4      '       d   K.   R# 	  V# )a«  True when a ``git stash apply`` failure is ONLY about untracked files that already exist in the tree.

Tail of the permission-denied class: push swept undeletable files into the stash but couldn't remove them;
apply restores tracked changes, then refuses to overwrite those files and exits non-zero though nothing was lost.
Any other error line (e.g. ``would be overwritten by merge``) means the tracked apply failed -> False.
Fc              3   óp   "  € T F,  qP                  4       '       g   K  VP                  4       x € K.  	  R # 5irH   )rI   )r*   Úlns   & r   r,   ÚA_stash_apply_failed_only_on_existing_untracked.<locals>.<genexpr>  s"   é € ÐNÑ$?˜bÇ8Á8Ç:Œzˆr�x‰x�zˆzÓ$?ùs   ‚6ž6rµ   zalready exists, no checkoutz,could not restore untracked files from stashT)zwarning:zhint:)rN   Ú
startswith)rf   Úsaw_untracked_errorr¿   s   &  r   Ú._stash_apply_failed_only_on_existing_untrackedrÃ     s[   € ð  ÐÙN V§\ \¨r×$=Ñ$=Ô$?ÖNˆØ(¨BÔ.Ð2`ÐdfÔ2fØ"&ÒØ—‘Ð4×5Ô5Úñ	 Oð
 Ðr   c                ó€   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\         \        ,          /# )r   r   r   rn   rf   r"   r   )r   s   "r   r   r     s<   € ÷ ñ ´´cµð Äð ÔRUð Ô_bð ÔgkÔloÕgpñ r   c           	     ó  € ^ RI Hp . pRpT;'       g    RP                  4        FÊ  pVP                  4       pVP	                  V4      '       g   K,  VR\        V4      )  pV! V RRRV 2.VRR	R
7      p	V	P                  ^ 8w  d   Ka  V! V RV RV 2.VRR	R
7      p
 \        V4      V,          P                  4       pV
P                  ^ 8w  g   WºP                  8w  g   K¹  VP                  V4       KÌ  	  V#   \         d    Rp LIi ; i)al  Paths ``git stash apply`` refused ("<path> already exists, no checkout") because the update
now tracks its own file there (``HEAD:<path>``) and the tree does not hold the stash's untracked
copy (``<stash>^3``). An untracked occupant HEAD does not track is the #70127 file that could
not be deleted at stash time, whatever its content now; it is never the update's.r   z already exists, no checkoutrµ   Nzcat-filez-ezHEAD:TF)r   r   rX   Úshowz^3:)r   r   rN   rI   Úendswithr)   r7   r   Ú
read_bytesr   r8   r    )r   r   rn   rf   r   ÚreplacedÚsuffixr¿   ÚrelÚtrackedÚstashedÚcurrents   &&&&        r   Ú#_untracked_files_replaced_by_updaterÏ     s  € õ
 2à€HØ+€FØ�|ˆ|˜×'Ñ'Ö)ˆØ�X‰X‹ZˆØ�{‰{˜6×"Ò"ÙØ�”C˜“K�<Ð ˆÙ˜' J°¸¸c¸U°mÐ#DÈ#Ð^bÐjoÔpˆØ×Ñ Ô"ÙÙ˜' F¨y¨k¸¸S¸EÐ,BÐ#CÈÐ]aÐinÔoˆð	Ü˜C“y 3•×2Ñ2Ó4ˆGð ×Ñ Ô" g·±Ö&?Ø�O‰O˜CÖ ñ *ð €Oøô	 ô 	ØŠGð	ús   Â C5Ã5DÄDc                ó(   € V ^8„  d   QhR\         RR/# )r   rn   r"   NrF   )r   s   "r   r   r   2  s   € ÷ Pñ P¤Sð P¨Tñ Pr   c                ó†   € \        4        \        R4       \        RV  24       \        RV  24       \        RV RRR7       R# )	z½Leave a pre-update autostash parked (``--keep-stash``, the desktop updater's mode): local source
edits must never be silently re-applied onto updated code; the entry stays in ``git stash``.uZ   â„¹ï¸�  Local changes were stashed before updating and were NOT re-applied (--keep-stash).ú  Stash ref: ú)  Restore manually with: git stash apply r²   z--keep-stashT©r¬   N)rJ   r·   )rn   s   &r   Ú_park_stashed_changesrÕ   2  s?   € ô 
„GÜ	Ð
fÔgÜ	ˆM˜)˜Ð
%Ô&Ü	Ð5°i°[Ð
AÔBÜ˜h¨	°>È$×Or   c                óv   € V ^8„  d   QhR\         \        ,          R\        R\        \        ,          R,          /# r=   ©r   r   r   Úset)r   s   "r   r   r   <  s-   € ÷ ñ ¤$¤s¥)ð ´$ð ¼3¼s½8Àd½?ñ r   c                óB   € \        V . ROV4      pVf   \        R4       V# )zCReturn untracked paths, or ``None`` when Git cannot enumerate them.uN     âš  Could not enumerate untracked files while validating the restored stash.)rY   z--othersz--exclude-standardr`   )r;   rJ   )r   r   Úpathss   && r   Ú_git_untracked_pathsrÛ   <  s%   € ä˜Ò"VÐX[Ó\€EØ‚}ÜÐ^Ô_Ø€Lr   c                óz   € V ^8„  d   QhR\         \        ,          R\        R\        \        R3,          R,          /# )r   r   r   r"   .N)r   r   r   r#   )r   s   "r   r   r   D  s2   € ÷  ñ  ¤D¬¥Ið  ´Dð  ¼UÄ3ÈÀ8½_ÈtÕ=Sñ  r   c                óÂ   € ^ RI Hp \        V . ROV4      pVf   \        R4       R# V! W4      pVf   R# VP	                  R V 4       4       \        \        V4      4      # )zuRestored ``.py`` paths changed from ``HEAD``; deliberately Python-only (entry scripts stay outside the health check).©rÛ   NuG     âš  Could not enumerate tracked Python files restored from the stash.c              3   óV   "  € T F  qP                  R 4      '       g   K  Vx € K!  	  R# 5i)z.pyN)rÇ   )r*   r:   s   & r   r,   Ú)_restored_python_paths.<locals>.<genexpr>N  s   é € ÐD¡)˜$¯}©}¸U×/C—’£)ùs   ‚)Ÿ
))Údiffú--name-onlyr`   rB   r[   z*.py)Úhermes_cli.update_cmdrÛ   r;   rJ   Úupdater#   Úsorted)r   r   rÛ   rÚ   Ú	untrackeds   &&   r   Ú_restored_python_pathsrç   D  sZ   € å:Ü˜Ò"UÐWZÓ[€EØ‚}ÜÐWÔXÙÙ$ WÓ2€IØÒÙØ	‡L�LÑD¡)ÓDÔDÜ”˜“ÓÐr   c                ó^   € V ^8„  d   QhR\         \        ,          R\        R\        R\        /# r|   ©r   r   r   rw   )r   s   "r   r   r   [  s,   € ÷ #ñ #¤T¬#¥Yð #´Tð #Äcð #Ìdñ #r   c                óf  € \        4       pW" R23 F)  p\        V RRRRV R2VR.V4      pVf    R# W5,          pK+  	  \        V R	R
RV R2.V4      pVf   R# VP                  ^ 8X  d$   \        V RRRRV R2.V4      pVf   R# W7,          pV'       g   R# \        V . ROV4      pVf   R# V F€  p	\	        V	4      P
                  P                  4       p
\	        V	4      P                  P                  4       \        9  g.   W,          P                  4       '       g   V
R8w  g   Kw  W¨9  g   K   R# 	  R# )a%  True only when every path the stash restores is demonstrably unable to change an import.

The set is read from the stash commit itself (worktree and index changes against its base,
renames split into delete + add, plus its untracked tree), never from the working tree,
which also holds what the clean import probe wrote. Each path must have an allowlisted
suffix, must not be a symlink, and may only sit in a directory ``HEAD`` already tracks, so
the restore cannot create a namespace-package directory. Any Git failure counts as
runtime-affecting.
z^2rá   râ   z--no-renamesr`   z^1r[   Frb   z-qrc   z^3úls-treeú-rTÚ.)rë   rì   z-drâ   r`   rB   )rØ   r;   r   r7   r   ÚparentÚas_posixrÊ   ÚlowerÚ_NON_RUNTIME_SUFFIXESÚ
is_symlink)r   r   rn   ÚrestoredÚsideÚchangedÚhas_untrackedræ   Ú	head_dirsr:   rî   s   &&&        r   Ú_restore_is_non_runtimerø   [  sJ  € ô ›€HØ˜k¨Ð,Ó-ˆÜØ�f˜m¨^¸TÀiÀ[ÐPRÐCSÐUYÐ[_Ð`ÐbeógˆàŠ?ÚØÕŠñ .ô ˜w¨°d¸JÈ9È+ÐUWÐHXÐ(YÐ[^Ó_€MØÒÙØ×Ñ 1Ô$Ü  ¨9°d¸MÈ4ÐT]ÐS^Ð^`ÐQaÐ*bÐdgÓhˆ	ØÒÙØÕˆßÙÜ˜WÒ&ZÐ\_Ó`€IØÒÙÛˆÜ�d“×"Ñ"×+Ñ+Ó-ˆÜ�‹J×Ñ×#Ñ#Ó%Ô-BÔBÀsÅz×F]ÑF]×F_ÒF_Ø˜c–M fÖ&=Úñ	 ñ
 r   c                óž   € V ^8„  d   QhR\         \        ,          R\        R\        R\        \        ,          R\        R\        R,          RR/# )	r   r   r   rn   Úpreexisting_untrackedÚfailing_targetr¯   Nr"   r×   )r   s   "r   r   r   �  sR   € ÷ $ñ $Ü”#�Yð$Ü!ð$Ü.1ð$ÜJMÌcÍ(ð$Üdgð$ä�$�Jð$ð 
ñ$r   c          	     ó”  € ^ RI Hp ^ RIHp \	        4        \	        R4       \	        RV 24       V'       d6   \        V4      P                  4       R,           F  p	\	        RV	 24       K  	  R R lp
V! W4      pVe	   W³,
          M	\        4       pT;'       g    T! R
R7      ;_uu_ 4        \        V . ROV4      pV'       d   \        V . RO\        V4      OV4      MR	pR	R	R	4       VR	J;'       d(    V
! X4      ;'       d    V'       * ;'       g	    V
! X4      pV'       d   V
! \        V . ROV4      4      pV'       d   \	        R4       M\	        R4       \	        R4       \	        R4       \	        RV 24       \	        RV 24       \	        RV 24       \        4        \        R4       \        ^4      h  + '       g   i     Lß; i)zIRestore the clean updated tree, preserve the stash, and abort the update.rÞ   ©rV   u>   âœ— Restored local changes made the Hermes agent unexecutable.z  Health check failed: :Né   Nr™   c                ó$   € V ^8„  d   QhR\         /# r�   )rw   )r   s   "r   r   Ú2_reject_unsafe_stash_restore.<locals>.__annotate__�  s   € ÷ =ñ =”tñ =r   c                 ó8   € V R J;'       d    V P                   ^ 8H  # rH   )r7   )r9   s   &r   Ú_okÚ)_reject_unsafe_stash_restore.<locals>._ok�  s    € Ø˜TÐ!×<Ð< f×&7Ñ&7¸1Ñ&<Ð<r   NTr]   zJ  The clean updated tree has been restored; the gateway was not restarted.uG     âš  The clean updated tree could not be fully restored automatically.zI    Inspect `git status` and run `git reset --hard HEAD` before retrying.zH  Platform connectivity alone does not mean the agent can execute turns.z0  Your local changes remain preserved in stash: z+  Inspect them with: git stash show --stat z6  Restore manually after fixing them: git stash apply Ústash_restore_rejectedr@   )Úcleanz-fdr[   )rá   z--quietrB   r[   )rã   rÛ   rd   rV   rJ   r   rN   rØ   r   rå   r�   r   Ú
SystemExit)r   r   rn   rú   rû   r¯   rP   rÛ   rV   rƒ   r  Úcurrent_untrackedÚrestored_untrackedrA   r  Ú
cleanup_oks   &&&&&&$         r   Ú_reject_unsafe_stash_restorer
  �  sŽ  € õ
 ;Ý2Ü	„GÜ	Ð
JÔKÜ	Ð# NÐ#3Ð
4Ô5ßÜ˜“K×*Ñ*Ó,¨R×0Ð0ˆDÜ�D˜˜�-Ö ñ 1õ=ñ -¨WÓ:ÐØFWÒFcÐ*ÖBÔilÓinÐØ
×
#Ð
#˜8Ð
#¨D×	1Ö	1Ü˜7Ò$?ÀÓEˆßas”
˜7Ò$W¼FÐCUÓ<VÐ$WÐY\Ô]Ðy}ˆ÷ 
2ð #¨$Ð.×hÐh±3°u³:×hÐhÐGYÔCY×CgÐCgÑ]`ÐafÓ]g€JßÙœ GÒ-NÐPSÓTÓUˆ
ßÜÐZÕ[äÐWÔXÜÐYÔZÜ	Ð
TÔUÜ	Ð<¸Y¸KÐ
HÔIÜ	Ð7¸	°{Ð
CÔDÜ	ÐBÀ9À+Ð
NÔOÜÔÜÐ)Ô*Ü
�Q‹-Ð÷# 
2×	1ús   Â,4F7Æ7G	c                ó0   € V ^8„  d   QhR\         R\        /# )r   rn   r"   r°   )r   s   "r   r   r   ¨  s   € ÷ ñ ¤ð ´$ñ r   c                óº  € VRJpV'       d   RMRp\        4        \        R4       \        R4       \        R4       \        RV 24       V'       d   V! RV 2R4      pM' \        4       P                  4       P                  4       pVR9   g   V'       g
   VR	8X  d   R
# \        R4       \        R4       \        RV  24       R#   \        \
        3 d    Rp LSi ; i)z\Interactive gate; a remote ``input_fn`` defaults to No (``[y/N]``), the local prompt to Yes.Nz[y/N]z[Y/n]u/   âš  Local changes were stashed before updating.zL  Restoring them may reapply local customizations onto the updated codebase.z=  Review the result afterward if Hermes behaves unexpectedly.zRestore local changes now? Únrµ   Tz Skipped restoring local changes.z.Your changes are still preserved in git stash.z'Restore manually with: git stash apply F>   ÚyÚyes)rJ   ÚinputrI   rð   ÚEOFErrorÚUnicodeDecodeError)rn   Úinput_fnÚremote_promptÚprompt_suffixÚresponses   &&   r   Ú_confirm_restorer  ¨  sÍ   € à DÐ(€Mß,‘G°'€MÜ	„GÜ	Ð
;Ô<Ü	Ð
XÔYÜ	Ð
IÔJÜ	Ð'¨ Ð
7Ô8ßÙÐ9¸-¸ÐIÈ3ÓO‰ð	Ü“w—}‘}“×,Ñ,Ó.ˆHð �<Ô¯¸(Àb¼.ÙÜ	Ð
,Ô-Ü	Ð
:Ô;Ü	Ð3°I°;Ð
?Ô@Ùøô Ô,Ð-ô 	ØŠHð	ús   Á &C ÃCÃCc          	      ó‚   € V ^8„  d   QhR\         \        ,          R\        R\        R\         \        ,          R,          /# ©r   r   r   rn   r"   Nr   )r   s   "r   r   r   À  s9   € ÷ "ñ "œ$œs�)ð "¬$ð "¼3ð "ÔW[Ô\_ÕW`ÐcgÕWgñ "r   c                ó@  € ^ RI Hp \        R4       T;'       g    T! V4      ;_uu_ 4       p\        WV4      w  rgV'       * ;'       d-    VP                  ^ 8H  ;'       g    \        VP                  4      VR&   RRR4       XR,          '       d   XP                  ^ 8X  d   . # VR,          '       d-   \        WVXP                  4      pV'       g   \        R4       V# \        R4       \        XP                  4       \        VP                  4       X'       d1   \        R4       VP                  4        F  p	\        RV	 24       K  	  \        R	4       \        R
V 24       \        R4       \        RV 24       \        RVR4       R#   + '       g   i     EL; i)a  ``git stash apply``; the untracked paths the update replaced (empty on a full restore), or
None (tree reset, stash kept) on conflicts or any failure other than the already-exists class.
``checkout_move`` binds the apply (and a conflict's reset) to the paused gateways' tree gate.rý   u   â†’ Restoring local changes...ÚwholeNuY     âš  Some stashed untracked files already exist in the working tree and were kept as-is.uF   âœ— Update pulled new code, but restoring local changes hit conflicts.z
Conflicted files:u     â€¢ u8   
Your stashed changes are preserved â€” nothing is lost.rÒ   z"Working tree reset to clean state.z1Restore your changes later with: git stash apply r²   zrestore hit conflicts)rd   rV   rJ   Ú_apply_stash_stepr7   rÃ   rf   rÏ   rK   r8   rN   r·   )
r   r   rn   rP   rV   ÚstepÚrestoreÚconflicted_filesrÉ   Úfs
   &&&&      r   Ú_apply_stashr!  À  se  € õ 3Ü	Ð
*Ô+Ø
×
#Ð
#˜8Ð
# Y×	/Ô	/°4Ü$5°gÀIÓ$NÑ!ˆð -Ô,÷ gð gØ×Ñ !Ñ#×eÐeÔ'UÐV]×VdÑVdÓ'eð 	ˆW‰÷	 
0ð ˆG‡}„}˜×+Ñ+¨qÔ0Øˆ	ØˆG‡}„}ô 7°wÀYÐPW×P^ÑP^Ó_ˆßÜÐmÔnØˆÜ	Ð
RÔSÜ�G—N‘NÔ#Ü�G—N‘NÔ#ßÜÐ#Ô$Ø!×,Ñ,Ö.ˆAÜ�F˜1˜#�,Öñ /ä	Ð
EÔFÜ	ˆM˜)˜Ð
%Ô&Ü	Ð
.Ô/Ü	Ð=¸i¸[Ð
IÔJÜ˜h¨	Ð3JÔKÙ÷9 
0×	/Ð	/ús   ¬3FÁ FÆF	c                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# )r   r   r   rn   r   )r   s   "r   r   r   å  s%   € ÷ %ñ %œt¤C�yð %¬tð %Äñ %r   c                óø   € ^ RI Hp V! V RRV.V4      pV! V . ROV4      pVP                  P                  4       pV'       g-   VP                  ^ 8w  d'   \        VP                  4      '       g   \        W4       WF3# )zÚ``git stash apply`` and its conflicted paths. Any failure but the already-exists class is
reset to the clean tree here, inside the bound step: conflict markers make hermes unrunnable,
and the changes stay in the stash.rs   rt   Úapply)rá   râ   z--diff-filter=U)rd   rU   r8   rI   r7   rÃ   rf   rC   )r   r   rn   rU   r  Úunmergedr  s   &&&    r   r  r  å  sq   € õ 3Ù�w ¨'°9Ð =¸sÓC€GÙ˜Ò!KÈSÓQ€HØ—‘×,Ñ,Ó.Ðß˜G×.Ñ.°!Ô3Ü$RÐSZ×SaÑSa×$bÒ$bÜ�GÔ!ØÐ$Ð$r   c                óV   € V ^8„  d   QhR\         \        ,          R\        R\        RR/# r  r   )r   s   "r   r   r   ó  s2   € ÷ Añ A¤$¤s¥)ð A´$ð AÄ3ð AÈ4ñ Ar   c                 ó^  € ^ RI Hp \        WV4      pVf(   \        R4       \        \        4       \        V4       R# V! V RRV.V4      pVP                  ^ 8w  dR   \        R4       \        VP                  4       \        VP                  4       \        \        4       \        W$4       R# R# )r?   rs   NuR   âš  Local changes were restored, but Hermes couldn't find the stash entry to drop.rt   ÚdropuP   âš  Local changes were restored, but Hermes couldn't drop the saved stash entry.)
rd   rU   rˆ   rJ   Ú_STASH_LEFT_IN_PLACEr»   r7   rK   r8   rf   ©r   r   rn   rU   r¹   r(  s   &&&   r   Ú_drop_restored_stashr+  ó  sŒ   € Ý2Ü,¨W¸9ÓE€NØÒÜÐbÔcÜÔ"Ô#Ü% iÔ0ÙÙ�G˜g v¨~Ð>ÀÓD€DØ‡�˜!ÔÜÐ`ÔaÜ˜Ÿ™Ô$Ü˜Ÿ™Ô$ÜÔ"Ô#Ü% iÖ@ñ r   c          
      ój   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\        /# )r   r   r   rn   Úprompt_userr"   ré   )r   s   "r   r   r     s:   € ÷ 5ñ 5Ü”#�Yð5Ü!ð5Ü.1ð5Ü@Dð5ô 
ñ5r   c          	      ó  a aaaa€ ^ RI HpHpHpHp	 V'       d$   \        SV4      '       g   \        RSRRR7       R# V! S S4      oSf)   \        R4       \        RS 24       \        RSR	4       R# V! SRR
7      p
\        S SSS4      pVf   R# R VVV VV3R llpV! S S4      pVf
   V! RR4       V	! SV4      w  rïpV'       g   T! T;'       g    RV4       \        S SS4      pV'       d   RMV! SRR
7      P                  4        F;  w  ppV
P                  V4      V8w  g   K  T! RT;'       g    R 2V^,          4        M	  V'       d‡   \        R\        V4       R24       VR,           F  p\        RV 24       K  	  \        R4       \        RS 24       \        RS R24       \        RSRRP                  VR,          4       24       R# \        S SS4       \        RS4       \        R4       \        R4       R# ) r?   )Ú _critical_module_import_failuresrÛ   rç   Ú_validate_python_files_syntaxr²   zrestore declinedTrÔ   FzE  The stash was not restored because its cleanup baseline is unknown.rÓ   zuntracked baseline unknown)Úreport_runtime_errorsc                ó(   € V ^8„  d   QhR\         RR/# )r   rû   r"   NrF   )r   s   "r   r   Ú._restore_stashed_changes.<locals>.__annotate__  s   € ÷ qñ qœsð q¨tñ qr   c           
      ó*   <€ \        SSSSWSR 7       R# ))rP   N)r
  )rû   r¯   rP   r   r   rú   rn   s   &&€€€€€r   ÚrejectÚ(_restore_stashed_changes.<locals>.reject  s   ø€ Ü$Ø�S˜)Ð%:¸NÐbo÷	qr   z restored Python source discoveryzBcould not determine which restored Python files require validationzrestored Python sourcezagent import Úunknownu   âš  The update added z8 file(s) where you had untracked files of the same name::Né
   Nr™   z]  The updated files are in place; your versions are kept in the stash, which was NOT dropped.rÒ   z   Recover a file with: git show z^3:<path> > <path>.minez(untracked files replaced by the update: z, ró   u?   âš  Local changes were restored on top of the updated codebase.zB  Review `git diff` / `git status` if Hermes behaves unexpectedly.rŠ   )rã   r/  rÛ   rç   r0  r  r·   rJ   r!  rø   ÚitemsÚgetr)   Újoinr+  )r   r   rn   r-  r  rP   r/  rÛ   rç   r0  Úclean_import_failuresrÉ   r5  Úrestored_pythonÚ	syntax_okÚfailing_pathÚsyntax_errorÚnon_runtimeÚmoduleÚerrorr:   rú   s   fff&&d               @r   Ú_restore_stashed_changesrD    s  ü€ ÷ Tó  TßÔ+¨I°x×@Ò@Ü! (¨IÐ7IÐRVÕWÙÙ0°¸#Ó>ÐØÒ$ÜÐUÔVÜÐ9¸)¸ÐEÔFÜ! (¨IÐ7SÔTÙÙ<¸SÐX\Ô]ÐÜ˜G S¨)°]ÓC€HØÒÙ÷qô qñ -¨W°cÓ:€OØÒÙÐ1Ð3wÔxÙ,IÈ#ÈÓ,_Ñ)€I˜\ßÙˆ|×7Ð7Ð7¸ÔFô
 *¨'°3¸	ÓB€Kß +™"Ù:¸3ÐVZÔ[×aÑaÓcòd‰ˆ�à ×$Ñ$ VÓ,°Ö5Ù�] 6×#6Ð#6¨YÐ"7Ð8¸%À½(ÔCÙñ	d÷
 äÐ%¤c¨(£m _Ð4lÐmÔnØ˜S—M�MˆDÜ�D˜˜�-Ö ñ "äÐmÔnÜ�˜i˜[Ð)Ô*ÜÐ0°°Ð;RÐSÔTÜ! (¨IÐ9aÐbf×bkÑbkÐltÐuxÕlyÓbzÐa{Ð7|Ô}ÙÜ˜ # yÔ1Ü˜j¨)Ô4Ü	Ð
KÔLÜ	Ð
NÔOÙr   c                ó^   € V ^8„  d   QhR\         \        ,          R\        R\        R\        /# r|   ré   )r   s   "r   r   r   <  s,   € ÷ ñ ¤d¬3¥ið ´dð Äsð Ìtñ r   c                ó@  € ^ RI Hp \        WV4      pVf   \        R4       \	        V4       R# V! V RRV.V4      pVP
                  ^ 8w  d;   \        R4       \        VP                  4       \	        W$4       \        RVR4       R# \        R	4       \        R
V4       R# )a  Drop a pre-update stash without applying (non-interactive ``updates.non_interactive_local_changes: discard``).

Unlike reset --hard + clean -fd this touches only what was stashed; ignored paths are never affected.
Returns True if dropped, False on git failure (stash left in place).
rs   ut   âš  Configured to discard local changes on non-interactive update, but Hermes couldn't find the stash entry to drop.Frt   r(  uX   âš  Configured to discard local changes, but Hermes couldn't drop the saved stash entry.r²   zconfigured discard faileduS   â†’ Discarded local source changes (updates.non_interactive_local_changes=discard).Ú	discardedT)	rd   rU   rˆ   rJ   r»   r7   rO   rf   r·   r*  s   &&&   r   Ú_discard_stashed_changesrH  <  s˜   € õ 3Ü,¨W¸9ÓE€NØÒÜð@ô	
ô 	& iÔ0ÙÙ�G˜g v¨~Ð>ÀÓD€DØ‡�˜!ÔÜÐhÔiÜ˜$Ÿ+™+Ô&Ü% iÔ@Ü! (¨IÐ7RÔSÙÜ	Ð
_Ô`Ü˜k¨9Ô5Ùr   c                óx   € V ^8„  d   Qh/ ^ \         9   d&   \        \        \        \        3,          ,          ;R&   # )r   re   )Ú__conditional_annotations__r   r#   r   r”   )r   s   "r   r   r      s-   € ÷ ñ ÷D 5Ò 4”HœU¤3¬ 8�_Õ-Ñ 4òEr   )rµ   rH   >   ú.mdú.gifú.icoú.jpgú.mdxú.pngú.rstú.svgú.txtú.adocú.jpegú.webp)FN)3rJ  Ú__doc__Úloggingr   r   r   r   r   r   Úpathlibr   Útypingr   Úhermes_cli.update_cmd_commonr   Ú	getLoggerr¢   ri   r›   r)  re   r   r0   r;   rC   rK   rO   rp   rj   rˆ   r�   r’   r«   r·   r»   rÃ   rÏ   rÕ   rÛ   rç   Ú	frozensetrñ   rø   r
  r  r!  r  r+  rD  rH  r   )rJ  s   @r   Ú<module>r^     s(  øðöó Û 	Û ß 7Ó 7Ý Ý å 5ð 
×	Ò	Ð2Ó	3€ð 4Ð ð Ð àmÐ ð 15Ð Ó 4õõõ @õP÷)õ
3ð
!ÐSW÷ !õHõ:õõRõ.ñbÐ`e÷ ð ÷ `õõ õ6Põõ ñ" "ò #ó Ð õ#ðL$à)-÷$õN÷0"õJ%õAñ"5à÷5ð 5÷pr   