+
    lHàjTb  ã                   óf  € R t ^ RIt^ RIt^ RIt^ RIHt ^ RIHtHt ^ RI	H
t
 ^ RIHt ^ RIHtHtHtHtHtHtHtHtHtHtHtHtHtHtHt ]P:                  ! ]4      tR R lt RR	 R
 llt!R R lt"R R R llt#R R lt$R!R R llt%R R lt&R R lt'R"R R llt(R R lt)R"R R llt*R"R R llt+R# )#z?Checkpoint store retention, orphan pruning, status and cleanup.N©ÚPath)ÚDictÚOptional)Úclear_stale_tmp_packs©Úrmtree_readonly)Ú_GIT_TIMEOUTÚ_LEGACY_PREFIXÚ_PRUNE_MARKER_NAMEÚ_REFS_PREFIXÚ_STORE_DIRNAMEÚ_dir_size_bytesÚ_index_pathÚ_list_projectsÚ_pre_v2_shadow_reposÚ_project_meta_pathÚ	_ref_nameÚ_resolve_checkpoint_baseÚ_run_gitÚ_store_has_headÚ_store_pathc                ó<   € V ^8„  d   QhR\         R\        R\        /# )é   ÚstoreÚrefÚreturn)r   ÚstrÚbool)Úformats   "ÚA/home/ubuntu/.hermes/hermes-agent/tools/checkpoint_maintenance.pyÚ__annotate__r!      s!   € ÷ ñ ”tð ¤#ð ¬$ñ ó    c                óZ   € \        RRV.V \        V P                  4      ^€0R7      w  p pV# )z6Delete a ref from the store.  Returns True on success.z
update-refz-d©Úallowed_returncodes)r   r   Úparent)r   r   ÚokÚ_s   &&  r    Ú_delete_refr)      s5   € äØ	�t˜SÐ! 5¬#¨e¯l©lÓ*;Ø ˜Eô�H€Bˆˆ1ð €Ir"   c          
      ó€   € V ^8„  d   QhR\         R\        \        ,          R\        \        ,          R\        R\        /# )r   ÚworkdirÚ
parent_devÚ
parent_inoÚrequire_parent_identityr   )r   r   Úintr   )r   s   "r    r!   r!   %   sI   € ÷ Uñ UÜðUäœ•ðUô œ•ðUô "ð	Uô
 
ñUr"   c                óÄ  € V '       g   R# \        V 4      p VP                  4       '       d   R# VP                  pWT8X  d   R# VP                  4       '       g   R# Ve6   Ve2   VP	                  4       pVP
                  VP                  3W38w  d   R# M
V'       d   R# \        V4      '       d   R# \        P                  P                  V4      #   \         d     R# i ; i)uÛ	  True only when we can positively observe that ``workdir`` was removed.

``Path.exists()`` returns False for a deleted directory AND for one whose
storage simply is not attached right now â€” an unplugged external drive, a
network share behind a downed VPN, a bind-mount absent from this
container, an offline Windows mapped drive. Orphan pruning deletes the
project's entire checkpoint history, so treating that ambiguity as
"deleted" throws away the user's restore points over a transient mount
state, unattended, at startup.

Require corroboration, in three steps.

First, the parent directory must be present, so the absence of the project
inside it is something we actually observed. When the parent is missing
too, the volume is not there and we know nothing.

Second, the present parent must be the directory we knew â€” not merely a
directory at the same path. Unmounting swaps the directory visible at a
mount point: while the volume is attached the path resolves to the
mounted filesystem's root; after detach it resolves to the *underlying*
(underlay) directory, which may carry entries of its own (a ``.keep``
placeholder, sibling mount points). Those entries were never next to the
project and prove nothing about the volume being attached. So the
parent's ``(st_dev, st_ino)`` must match the identity recorded in the
project's metadata while the project was observably live
(``parent_dev``/``parent_ino``). A mismatch means a different directory
is visible at that path â€” a detached volume, not an observed deletion.
When no identity was ever recorded (metadata written by an older
version) and ``require_parent_identity`` is True, stay conservative and
do not classify as orphan. Callers that have no identity channel at all
(the frozen pre-v2 layout) pass ``require_parent_identity=False`` to
keep the structural checks only.

Third, the (identity-confirmed) parent must actually carry information.
Unmounting leaves classic static mount points (``/mnt/volume/proj``, an
fstab entry, a container bind-mount) behind as *empty* directories, so an
empty parent is the signature of a detached volume just as much as of a
deleted project. Prune only when the parent holds something else (we
observed a populated directory that does not contain the project) or is
itself a live mount point (the volume is demonstrably attached and the
project is demonstrably not on it).

Genuinely abandoned projects are still reclaimed by the retention/stale
rule, which runs off ``last_touch`` rather than a filesystem probe.
FT)r   Úexistsr&   Úis_dirÚstatÚst_devÚst_inoÚ_dir_has_any_entryÚosÚpathÚismountÚOSError)r+   r,   r-   r.   r8   r&   Ústs   &&&&   r    Ú_workdir_is_observably_goner<   %   sÀ   € ÷f ÙÜ�‹=€DðØ�;‰;�=Š=ÙØ—‘ˆð Œ>ÙØ�}‰}�ŠÙØÒ! jÒ&<Ø—‘“ˆBØ—	‘	˜2Ÿ9™9Ð%¨*Ð)AÔAñ ð	 B÷
 %ñ Ü˜f×%Ò%Ùô
 �w‰w�‰˜vÓ&Ð&øÜô âðús4   —C ¯C ÁC Á6C ÂC ÂC Â1C ÃCÃCc                ó0   € V ^8„  d   QhR\         R\        /# )r   Ú	directoryr   )r   r   )r   s   "r    r!   r!   }   s   € ÷ 	ñ 	¤$ð 	¬4ñ 	r"   c                ó    € \         P                  ! V 4      ;_uu_ 4       pV F  p RRR4       R# 	  RRR4       R#   + '       g   i     R# ; i)zŸTrue when ``directory`` contains at least one entry.

Stops after the first entry rather than materializing the listing; a
project root can hold a large tree.
NTF)r7   Úscandir)r>   Úentriesr(   s   &  r    r6   r6   }   s@   € ô 
�Š�I×	Ô	 'ÛˆAØ÷ 
Ñ	Ù÷ 
ñ ÷ 
Ö	ñ ús   Ÿ<°<¼A	c                ó®   € V ^8„  d   QhR\         R\        R\        \        ,          R\         R\        \        ,          R\
        \        \         3,          /# )r   Úretention_daysÚdelete_orphansÚcheckpoint_baseÚmax_total_size_mbÚorphan_allowlistr   )r/   r   r   r   ÚsetÚdictr   )r   s   "r    r!   r!   ‰   sT   € ÷ 9ñ 9Üð9äð9ô œd•^ð9ô ð	9ô
 œs•mð9ô 
Œ#Œsˆ(…^ñ9r"   c           
     óŠ  € T;'       g    \        4       pR^ R^ R^ R^ R^ /pVP                  4       '       g   V# ^ RIHpHp  V! V4      ;_uu_ 4        \        WVWW44      uuRRR4       #   + '       g   i     R# ; i  T\        3 d8   p	TR;;,          ^,          uu&   \        P                  RT	4       Tu Rp	?	# Rp	?	ii ; i)	u_  Delete stale/orphan checkpoints and reclaim store space.

A project entry is deleted when either:

* ``delete_orphans=True`` and its ``workdir`` no longer exists on disk
  (the original project was deleted / moved); OR
* its ``last_touch`` is older than ``retention_days`` days.

``orphan_allowlist``, when not ``None``, restricts orphan deletion to
the given identities (v2 project ``_hash`` strings and/or pre-v2 shadow
repo paths as ``str``). This lets a caller that showed the user a
confirmation preview (built from ``store_status()``) bind the resulting
deletion to exactly what was displayed â€” a project that only becomes
orphaned *after* the preview (e.g. its workdir vanishes while the human
is answering the prompt) is skipped rather than swept up under the
earlier confirmation. Pass ``None`` (the default) to delete every
currently-orphaned project, e.g. for ``--force`` or unattended callers
that never show a preview.

Additionally, if ``max_total_size_mb > 0`` and the store exceeds that
after orphan/stale pruning, the oldest commit per remaining project is
dropped until the store is under the cap.

Legacy-archive dirs (``legacy-*``) older than ``retention_days`` are
also deleted.

Returns a dict with counts ``{"scanned", "deleted_orphan",
"deleted_stale", "errors", "bytes_freed"}``.

Never raises â€” maintenance must never block interactive startup.
ÚscannedÚdeleted_orphanÚdeleted_staleÚerrorsÚbytes_freed)Ú
PruneErrorÚ
store_lockNz"Checkpoint maintenance stopped: %s)	r   r1   Útools.checkpoint_pruningrP   rQ   Ú_prune_checkpointsr:   ÚloggerÚwarning)
rC   rD   rE   rF   rG   ÚbaseÚresultrP   rQ   Úexcs
   &&&&&     r    Úprune_checkpointsrY   ‰   s¯   € ðL ×8Ð8Ô6Ó8€Dà�1Ø˜!Ø˜Ø�!Ø�qð€Fð �;‰;�=Š=Øˆç?ðÙ˜×ÕÜ% d°NÐTeÓx÷ ××ÓûàœÐ ô Øˆx×˜AÕÓÜ�‰Ð;¸SÔAØ�ûðús<   ÁA> ÁA*Á
A> Á*A;	Á5A> Á;A> Á>CÂ,B=Â7CÂ=Cc                óÆ   € V ^8„  d   QhR\         R\        \        \        3,          R\        R\        R\        R\
        \        ,          R\        \        \        3,          /# )r   rV   rW   rC   rD   rF   rG   r   )r   rI   r   r/   r   r   rH   )r   s   "r    r!   r!   Å   sc   € ÷ eñ eÜ
ðeÜœS¤#˜X�ðeÜ8;ðeÜMQðeäðeä.6´s­mðeô 
Œ#Œsˆ(…^ñer"   c                 óÀ  € \        V 4      pR pV^ 8”  d$   \        P                  ! 4       VR,          ,
          pV P                  4        FÆ  pVP                  4       '       g   K  VP                  \
        8X  d   K2  VP                  P                  \        4      '       g   KY  V^ 8:  d   Kb   VP                  4       P                  p	Y—8¼  d   K…   \        T4      p
\        T4       TR;;,          T
,          uu&   TR;;,          ^,          uu&   KÈ  	  \        V 4       EF8  pVR,          pVR;;,          ^,          uu&   RpV'       dK   VR	,          '       g<   VR
,          e   \        VR
,          RR7      '       d   Ve   \!        V4      V9   d   RpVfY   V^ 8”  dR   R p VP#                  R4       F*  p VP                  4       P                  p\%        VV4      pK,  	  V^ 8”  d	   Wç8  d   RpVf   KØ   \        V4      p
\        V4       VR;;,          V
,          uu&   VR8X  d   VR;;,          ^,          uu&   EK#  VR;;,          ^,          uu&   EK;  	  \'        V 4      pVR,          P)                  4       '       Edû   \+        V4       \-        V4       EF  pVP/                  R4      ;'       g    RpVP/                  R
4      ;'       g    RpV'       g   KD  VR;;,          ^,          uu&   RpVP/                  R4      pVP/                  R4      p\1        V\2        4      '       d   \1        V\4        4      '       d   Rp\1        V\2        4      '       d   \1        V\4        4      '       d   RpV'       d+   V'       d   \        VVVR7      '       d   Ve   VV9   d   RpM<V^ 8”  d6   \7        VP/                  R^ 4      ;'       g    ^ 4      pV^ 8”  d
   VV8  d   RpVf   EKN  \9        V4      p\;        VV4      '       g   VR;;,          ^,          uu&   Vu #  \=        VV4      pVP)                  4       '       d   VP?                  4         \A        TT4      pTP)                  4       '       d   TP?                  4        TR8X  d   TR;;,          ^,          uu&   EK	  TR;;,          ^,          uu&   EK!  	  ^ RI!H"pH#p V! \H        V\!        V 4      \J        \         \L        4      p VR,          VR,          ,           '       g   VPO                  4       '       d   VPQ                  4        VPS                  VR,          R,          4      '       g+   VR;;,          ^,          uu&   \        P                  R4       \        V 4      pVV,
          p\%        VR,          V4      VR&   V#   \         d     EKp  i ; i  \         d8   pTR;;,          ^,          uu&   \        P                  RY‹4        Rp?EK±  Rp?ii ; i  \         d     EK^  i ; i  \         d     ELBi ; i  \         dC   pTR;;,          ^,          uu&   \        P                  RTP                  T4        Rp?EKQ  Rp?ii ; i  \         d     EL4i ; i  \         d     ELi ; i  T\        3 d7   pTR;;,          ^,          uu&   \        P                  RT4        Rp?EL[Rp?ii ; i)g        i€Q rO   rM   rN   z&Failed to delete legacy archive %s: %sNr8   rK   Úmarker_unreadabler+   F)r.   ÚorphanÚ*ÚstalerL   z&Failed to prune checkpoint repo %s: %sÚHEADÚ_hashÚ Úworkdir_parent_devÚworkdir_parent_ino)r,   r-   Ú
last_touch)ÚPrunerrP   é   zDCheckpoint store remains over its size cap; minimum history retainedzCheckpoint pruning stopped: %s)*r   ÚtimeÚiterdirr2   Únamer   Ú
startswithr
   r3   Úst_mtimer:   r   rT   rU   r   r<   r   ÚrglobÚmaxr   r1   r   r   ÚgetÚ
isinstancer/   r   Úfloatr   r)   r   Úunlinkr   rR   rf   rP   r   r	   r   Ú
gc_pendingÚreclaimÚenforce_size) rV   rW   rC   rD   rF   rG   Úsize_beforeÚcutoffÚchildÚmÚsizerX   ÚrepoÚreasonÚnewestÚpÚmtr   ÚmetaÚdir_hashr+   r,   r-   re   r   ÚidxÚmprf   rP   ÚprunerÚ
size_afterÚdeltas    &&&&&&                          r    rS   rS   Å   s½  € ô " $Ó'€Kð €FØ˜ÔÜ—’“˜~°Õ5Õ5ˆà—‘–ˆØ�|‰|�~Š~ÙØ�:‰:œÔ'ÙØ�:‰:× Ñ ¤×0Ô0à Ô"ÙðØ—J‘J“L×)Ñ)�ð Œ{ÙðUÜ& uÓ-�Ü Ô&Ø�}×%¨Õ-Ó%Ø�×'¨1Õ,Õ'ñ'  ô6 % T×*ˆØ�V•ˆØˆy×˜QÕÓØ $ˆçØÐ,×-Ô-à�Y•Ò'ô /Ø˜•O¸U÷ó ð "Ò)¬S°«ZÐ;KÔ-KàˆFØŠ>˜n¨qÔ0ØˆFðØŸ™ SÖ)�Að!ØŸV™V›X×.Ñ.˜Ü!$ V¨R£šñ *ð ˜Œz˜fœoØ �ØŠ>Ùð
	VÜ" 5Ó)ˆDÜ˜EÔ"Ø�=×! TÕ)Ó!Ø˜Ô!ØÐ'×(¨AÕ-Ö(à�×'¨1Õ,Ö'ñS +ô^ ˜Ó€EØ��×Ñ× Ó ô 	˜eÔ$Ü" 5×)ˆDØ—x‘x Ó(×.Ð.¨BˆHØ—h‘h˜yÓ)×/Ð/¨RˆGßÙØ�9× Õ"ÓØˆFØŸ™Ð"6Ó7ˆJØŸ™Ð"6Ó7ˆJÜ˜j¬#×.Ò.´*¸ZÌ×2NÒ2NØ!�
Ü˜j¬#×.Ò.´*¸ZÌ×2NÒ2NØ!�
ççÜ2ØØ#-Ø#-÷ó ð &Ò-°Ð=MÔ1Mà!‘Ø !Ô#Ü" 4§8¡8¨L¸!Ó#<×#AÐ#AÀÓB�
Ø ”> j°6Ô&9Ø$�FØŠ~ÚÜ˜HÓ%ˆCÜ˜u c×*Ò*Ø�x×  AÕ%Ó Ø’ðÜ! %¨Ó2�Ø—:‘:—<’<Ø—J‘J”LðÜ'¨¨xÓ8�Ø—9‘9—;’;Ø—I‘I”Kð ˜Ô!ØÐ'×(¨AÕ-Ö(à�×'¨1Õ,Ö'ñi *÷l 	@áœ %¬¨T«´LÄ/ÔS_Ó`ˆð	BØÐ&Õ'¨&°Õ*A×AÔAÀV×EVÑEV×EXÒEXØ—‘Ô Ø×&Ñ&Ð'8¸4Õ'?À$Õ'F×GÒGØ�x×  AÕ%Ó Ü—‘ÐeÔfô
 ! Ó&€JØ˜*Õ$€EÜ  }Õ 5°uÓ=€Fˆ=Ñà€MøôY ô Ûðûô ô UØ�x×  AÕ%Ó Ü—‘ÐGÈ×TÓTûðUûôB #ô !Û ð!ûäô Úðûô ô 	VØ�8× Õ!ÓÜ�N‰NÐCÀUÇZÁZÐQT×UÓUûð	Vûôh ô Úðûô ô Úðûð  œGÐ$ô 	BØ�8× Õ!ÓÜ�N‰NÐ;¸S×AÒAûð	BúsÈ   Â+V)ÃA V<Æ!XÆ6&XÇXÇ6AX&É X&Ð2Y6Ñ2ZÓ+2Z Ô4Z Õ*Z Ö)V9Ö8V9Ö<W>×+W9×9W>ØXØXØXØXØX#Ø"X#Ø&Y3Ø16Y.Ù.Y3Ù6ZÚZÚZÚZÚ[Ú'+[Û[c                ó˜   € V ^8„  d   QhR\         R\         R\        R\        \        ,          R\         R\        \
        \        3,          /# )r   rC   Úmin_interval_hoursrD   rE   rF   r   )r/   r   r   r   rI   r   Úobject)r   s   "r    r!   r!   m  sQ   € ÷ 9ñ 9Üð9äð9ô ð9ô œd•^ð	9ô
 ð9ô 
Œ#Œvˆ+Õñ9r"   c           
     ó„  € T;'       g    \        4       pRR/p VP                  4       '       g   R^ R^ R^ R^ R^ /VR&   V# V\        ,          p\        P                  ! 4       p VP                  4       '       dD   V\	        VP                  R	R
7      P                  4       4      ,
          VR,          8  d   RVR&   V#  TP                  \        T4      RR
7       \        YYTR7      ;q¦R&   T
R,          T
R,          ,           pT^ 8”  d6   \        P                  RTT
R,          T
R,          T
R,          R,          4       T#   \        \        3 d     L–i ; i  \         d!   p	\        P                  RT	4        Rp	?	L£Rp	?	ii ; i  \         d0   p	\        P!                  RT	4       \        T	4      TR&    Rp	?	T# Rp	?	ii ; i)a  Idempotent wrapper around ``prune_checkpoints`` for startup hooks.

Writes ``CHECKPOINT_BASE/.last_prune`` on completion so subsequent
calls within ``min_interval_hours`` short-circuit.

Returns ``{"skipped": bool, "result": prune_checkpoints-dict,
"error": optional str}``.
ÚskippedFrK   rL   rM   rN   rO   rW   z	utf-8-sig)Úencodingi  Tzutf-8z+Could not write checkpoint prune marker: %sN)rC   rD   rE   rF   zZcheckpoint auto-maintenance: pruned %d entry(ies) (%d orphan, %d stale), reclaimed %.1f MBz&checkpoint auto-maintenance failed: %sÚerrori   )r   r1   r   rh   rq   Ú	read_textÚstripr:   Ú
ValueErrorÚ
write_textr   rT   ÚdebugrY   ÚinfoÚ	ExceptionrU   )rC   rˆ   rD   rE   rF   rV   ÚoutÚmarkerÚnowrX   rW   Útotals   &&&&&       r    Úmaybe_auto_prune_checkpointsr™   m  s»  € ð ×8Ð8Ô6Ó8€DØ'¨Ð/€Cð% Ø�{‰{�}Š}à˜1Ð.°°?ÀAØ˜!˜]¨AðˆC�‰Mð ˆJàÔ*Õ*ˆÜ�iŠi‹kˆð	Ø�}‰}�Š 3¬¨v×/?Ñ/?ÈÐ/?Ó/U×/[Ñ/[Ó/]Ó)^Õ#^ÐasÐvzÕazÔ#zØ!%��I‘Ø�
ð
	MØ×Ñœc #›h°ÐÔ9ô "3À.ØCGô"nð 	nˆ�X‘ð Ð'Õ(¨6°/Õ+BÕBˆØ�1Œ9Ü�K‰Kð;àØÐ'Õ(Ø�Õ'Ø�}Õ%¨Õ5ôð €Jøô3 œÐ$ô 	Ùð	ûô ô 	MÜ�L‰LÐFÈ×LÑLûð	Mûô ô  Ü�‰Ð?ÀÔEÜ˜3“xˆˆG�à€Jûð	 úsr   šF °F Á"F Á$E  Á:AE  Â>E ÃA$F Å EÅF ÅEÅF ÅFÅ"E=Å8F Å=FÆF ÆF?Æ$F:Æ:F?c                óF   € V ^8„  d   QhR\         \        \        3,          /# ©r   r   )rI   r   r‰   )r   s   "r    r!   r!   ©  s   € ÷ 4ñ 4¤¤S¬& [Õ 1ñ 4r"   c                 ó¶  €  ^ RI Hp  V ! 4       P                  R4      ;'       g    / pVP                  RR4      '       g   RR/# \        \	        VP                  R^4      4      \	        VP                  R^4      4      R\	        VP                  R	R
4      4      R7      #   \
         d0   p\        P                  RT4       RRR\        T4      /u Rp?# Rp?ii ; i)uW  ``maybe_auto_prune_checkpoints`` driven by the ``checkpoints:`` config section â€” the one
startup/housekeeping entry point for the CLI and the gateway. ``delete_orphans`` is never
honoured unattended: a missing workdir is ambiguous (deleted vs. unmounted share); orphan
cleanup is only via explicit ``hermes checkpoints prune``. Never raises.©Úload_configÚcheckpointsÚ
auto_pruneFr‹   TrC   rˆ   rF   éô  )rC   rˆ   rD   rF   z'checkpoint auto-maintenance skipped: %sr�   N)	Úhermes_cli.configrž   ro   r™   r/   r”   rT   r’   r   )rž   ÚcfgrX   s      r    Úauto_prune_from_configr¤   ©  sÂ   € ð
4Ý1Ù‹m×Ñ Ó.×4Ð4°"ˆØ�w‰w�| U×+Ò+Ø˜tÐ$Ð$Ü+Ü˜sŸw™wÐ'7¸Ó;Ó<Ü" 3§7¡7Ð+?ÀÓ#DÓEØ Ü! #§'¡'Ð*=¸sÓ"CÓDô	Fð 	Føô
 ô 4Ü�‰Ð>ÀÔDØ˜4 ¬#¨c«(Ð3Õ3ûð4ús/   ‚"B ¥B Á B ÁAB ÂCÂ)$CÃCÃCc                ó:   € V ^8„  d   QhR\         \        ,          /# r›   )r   r   )r   s   "r    r!   r!   ½  s   € ÷ ñ ¤X¬c¥]ñ r"   c                 ó(  €  ^ RI Hp  V ! 4       P                  R4      ;'       g    / pVP                  RR4      '       g   R# \        VP                  RR4      ;'       g    ^ 4      pV^ 8:  d   R# \	        4       p\        V4      pWBR,          R,          8  d   R# \        V4      p\        V4      '       d   \        \        V4      4      M^ p^ R	I
Hp R
V! V4       RV RV R2#   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)uÂ  One-line notice when ``/rollback`` checkpoints are on and their store sits at or above
``checkpoints.max_total_size_mb``, else None. Checkpoints were on by default for a while
(Marâ€“May 2026) and that ``enabled: true`` persisted into user configs; many users carry a
GB-scale store for a feature they never invoke. The cap is a floor of one snapshot per
project, so a big store is expected, not broken â€” the notice names the opt-out. Never raises.r�   rŸ   ÚenabledFNrF   r¡   rg   )Úformat_bytesz+Filesystem checkpoints (/rollback) are on: z across z project(s), above the z½ MB cap (one snapshot per project is always kept). Not using /rollback? `hermes config set checkpoints.enabled false` then `hermes checkpoints clear`; or lower `checkpoints.retention_days`.z'checkpoint footprint notice skipped: %s)r¢   rž   ro   r/   r   r   r   r   Úlenr   Úhermes_cli.sizefmtr¨   r”   rT   r’   )	rž   r£   Úcap_mbrV   rz   r   Úproject_countr¨   rX   s	            r    Úcheckpoint_footprint_noticer­   ½  s   € ðÝ1Ù‹m×Ñ Ó.×4Ð4°"ˆØ�w‰w�y %×(Ò(ÙÜ�S—W‘WÐ0°#Ó6×;Ð;¸!Ó<ˆØ�QŒ;ÙÜ'Ó)ˆÜ˜tÓ$ˆØ˜4•- $Õ&Ô&Ùä˜DÓ!ˆÜ6EÀe×6LÒ6LœœN¨5Ó1Ô2ÐRSˆÝ3Ø=¹lÈ4Ó>PÐ=QÐQYØ �/Ð!8¸¸ð AUðVð 	Wøô ô Ü�‰Ð>ÀÔDÝûðús5   ‚"C% ¥C% ÁC% Á C% Á0)C% ÂA	C% Ã%DÃ0DÄDc                óF   € V ^8„  d   QhR\         \        ,          R\        /# ©r   rE   r   )r   r   rI   )r   s   "r    r!   r!   à  s"   € ÷ Qñ Q¤(¬4¥.ð Q¼Dñ Qr"   c                óÒ  € T ;'       g    \        4       pR\        V4      R^ R^ R^ R^ R. R. R. /pVP                  4       '       g   V# \        V4      pVP                  4       '       Ed    \	        V4      VR&   VR	,          P                  4       '       dõ   \        V4       Få  pVP                  R
4      ;'       g    RpVP                  R4      ;'       g    Rp\        V4      p\        RRV.V\        V4      ^€0R7      w  r‰p
 V'       d   \        V	4      M^ pVR,          P                  RTRTR\        V4      ;'       d    \        V4      P                  4       RVP                  R4      RVP                  R4      RV/4       Kç  	  \        VR,          4      VR&   \        V4       Uu. uF)  pR\        VR,          4      RVR,          RVR,          /NK+  	  upVR&   VP!                  4        F¦  pVP#                  4       '       g   K  VP$                  P'                  \(        4      '       g   KB   \	        V4      pVR;;,          V,          uu&    VP-                  4       P.                  pVR,          P                  RVP$                  RVRV/4       K¨  	  \	        V4      VR&   V#   \         d    ^ p EL¡i ; iu upi   \*         d    ^ p L”i ; i  \*         d    ^ p Lwi ; i)uF  Return a summary of the shadow store.

``{"base": path, "store_size_bytes": N, "legacy_size_bytes": N,
   "total_size_bytes": N, "project_count": N, "projects": [...],
   "pre_v2_projects": [...], "legacy_archives": [...]}``

``pre_v2_projects`` covers shadow repos still on the pre-v2 per-project
layout (``base/<hash>/HEAD``) â€” distinct from ``legacy_archives``, which
are already-migrated ``legacy-<ts>/`` dirs. Callers that preview an
orphan-deletion sweep must include both ``projects`` and
``pre_v2_projects``, since ``prune_checkpoints`` deletes orphans from
both layouts.
rV   Ústore_size_bytesÚlegacy_size_bytesÚtotal_size_bytesr¬   ÚprojectsÚpre_v2_projectsÚlegacy_archivesr`   ra   rb   r+   zrev-listz--countr$   Úhashr1   Ú
created_atre   Úcommitsr8   rj   Ú
size_bytesÚmtime)r   r   r1   r   r   r   ro   r   r   r/   r�   Úappendr   r   r©   r   ri   r2   rj   rk   r
   r:   r3   rl   )rE   rV   r•   r   r€   r�   r+   r   r'   Ú	count_outr(   r¹   Úrrx   rz   r   s   &               r    Ústore_statusr¿   à  sÉ  € ð ×8Ð8Ô6Ó8€Dà”�D“	Ø˜AØ˜QØ˜AØ˜Ø�BØ˜2Ø˜2ð	€Cð �;‰;�=Š=Øˆ
ä˜Ó€EØ‡|�|‡~ƒ~Ü"1°%Ó"8ˆÐÑØ�F�N×"Ñ"×$Ò$Ü& uÖ-�ØŸ8™8 GÓ,×2Ð2°�ØŸ(™( 9Ó-×3Ð3°�Ü Ó)�Ü#+Ø ¨CÐ0°%¼¸T»Ø),¨ô$Ñ �˜qð ß02œc )œn¸�Gð �J•×&Ñ&Ø˜HØ˜wØœd 7›m×FÐF´°W³×0DÑ0DÓ0FØ  $§(¡(¨<Ó"8Ø  $§(¡(¨<Ó"8Ø˜wð(ö ñ .ô( ˜s :�Ó/€CˆÑô & dÔ+óñ ,ˆAð	 ”C˜˜&�	“NØ�q˜•|Ø�a˜•kó	
ñ
 ,ñ€CÐÑð —‘–ˆØ�<‰<�>Œ>˜eŸj™j×3Ñ3´N×CÔCðÜ& uÓ-�ð Ð#×$¨Õ,Ó$ðØ—Z‘Z“\×*Ñ*�ð Ð!Õ"×)Ñ)Ø˜Ÿ
™
Ø˜dØ˜ð+ö ñ  ô" .¨dÓ3€CÐÑØ€JøôO "ô  Ø“Gð üòøô ô Ø’ðûô
 ô Ø’ðús<   ÄJ*Æ+/J>È3KÉKÊ*J;Ê:J;ËKËKËK&Ë%K&c                ó(   € V ^8„  d   QhR\         RR/# )r   r8   r   Nr   )r   s   "r    r!   r!   4  s   € ÷ ñ œð  ñ r"   c                 ó   € \        V 4       R # ©Nr   )r8   s   &r    Ú_rmtree_forcerÃ   4  s
   € Ü�DÖr"   c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# r¯   ©r   r   rI   r   r/   )r   s   "r    r!   r!   8  s&   € ÷ ñ œx¬�~ð ¼¼cÄ3¸h½ñ r"   c                óx  € T ;'       g    \        4       pR^ RR/pVP                  4       '       g   V# \        V4      p ^ RIHp V! V4      ;_uu_ 4        \        V4       RRR4       W2R&   RVR&   V#   + '       g   i     L; i  \        \        3 d"   p\        P                  RY4        Rp?T# Rp?ii ; i)zsNuke the entire checkpoint base (store + legacy).  Irreversible.

Returns ``{"bytes_freed": N, "deleted": bool}``.
rO   ÚdeletedF©rQ   NTz&Could not clear checkpoint base %s: %s)
r   r1   r   rR   rQ   rÃ   r:   ÚRuntimeErrorrT   rU   )rE   rV   r•   rz   rQ   rX   s   &     r    Ú	clear_allrÊ   8  s®   € ð
 ×8Ð8Ô6Ó8€DØ˜!˜Y¨Ð
.€CØ�;‰;�=Š=Øˆ
Ü˜4Ó €DðLÝ7á˜×ÕÜ˜$Ô÷ à!ˆMÑØˆˆI‰ð €J÷ ×ûô ”\Ð"ô LÜ�‰Ð?À×KÐKØ€JûðLús/   ¿B ÁA4Á!B Á4B	Á?B ÂB9ÂB4Â4B9c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# r¯   rÅ   )r   s   "r    r!   r!   N  s&   € ÷ ñ ¤(¬4¥.ð ¼DÄÄcÀ½Nñ r"   c           	     ó.  € T ;'       g    \        4       pR^ R^ R^ /pVP                  4       '       g   V# ^ RIHp  V! V4      ;_uu_ 4        \	        VP                  4       4       F�  pVP                  4       '       d&   VP                  P                  \        4      '       g   K@   \        V4      p\        V4       VR;;,          V,          uu&   VR;;,          ^,          uu&   Kƒ  	  RRR4       V#   \         d7   pTR;;,          ^,          uu&   \        P                  RYF4        Rp?KË  Rp?ii ; i  + '       g   i     T# ; i  \        \        3 d7   pTR;;,          ^,          uu&   \        P                  RT4        Rp?T# Rp?ii ; i)zDDelete all ``legacy-*`` archive directories and report any failures.rO   rÇ   rN   rÈ   z&Could not delete legacy archive %s: %sNz#Could not clear legacy archives: %s)r   r1   rR   rQ   Úlistri   r2   rj   rk   r
   r   rÃ   r:   rT   rU   rÉ   )rE   rV   r•   rQ   rx   rz   rX   s   &      r    Úclear_legacyrÎ   N  sC  € à×8Ð8Ô6Ó8€DØ˜!˜Y¨¨8°QÐ
7€CØ�;‰;�=Š=Øˆ
Ý3ðCÙ˜×ÕÜ˜dŸl™l›nÖ-�Ø—|‘|—~’~¨U¯Z©Z×-BÑ-BÄ>×-RÒ-RÙðYÜ*¨5Ó1�DÜ! %Ô(Ø˜×&¨$Õ.Ó&Ø˜	—N aÕ'•Nñ .÷ ð €Jøô ô YØ˜—M QÕ&“MÜ—N‘NÐ#KÈU×XÒXûðYú÷ Öð €Jûô ”\Ð"ô CØˆH�˜Õ‹Ü�‰Ð<¸c×BÐBØ€JûðCúsg   ¼E ÁAD9Â$D9Â'A C5Ã'D9Ã+E Ã5D6	Ä +D1	Ä+D9Ä1D6	Ä6D9Ä9E
	ÅE Å
E ÅFÅ+FÆF)NNT)é   TNé    N)rÏ   é   TNrÐ   rÂ   ),Ú__doc__Úloggingr7   rh   Úpathlibr   Útypingr   r   Úhermes_cli.gitlockr   Úutilsr   Útools.checkpoint_managerr	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   Ú	getLoggerÚ__name__rT   r)   r<   r6   rY   rS   r™   r¤   r­   r¿   rÃ   rÊ   rÎ   © r"   r    Ú<module>rÜ      s’   ðÙ Eã Û 	Û Ý ß !å 4Ý !÷÷ ÷ ÷ ñ ð 
×	Ò	˜8Ó	$€õ÷Uõp	÷9õxe÷P9õx4õ(÷FQõh÷÷,ñ r"   