+
    ƒWÝj<o  ã                  ó  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Ht ^ RIHt ^ RIHt ^ RIHtHtHtHtHt ^ RIHt ^ RIHt ^ R	IHt ^ R
IHt ]P>                  ! ] 4      t!Rt"R]#R&   Rt$Rt%Rt&RVt']PP                  ! 4       t)]
PT                  ! 4       PV                  t,R R lt-R R lt.]R R l4       t/R R lt0RR/R R llt1R R lt2R R lt3R R  lt4R! R" lt5R# R$ lt6R% R& lt7R' R( lt8R)R/R* R+ llt9R, R- lt:R. R/ lt;R0 R1 lt<R2 R3 lt=R4RRR/R5 R6 llt>R4RRR/R7 lt?R8 t@R9 R: ltAR; R< ltBR= R> ltCR?tDR@tERA RB ltFRC RD ltGRE RF ltHRG RH ltIRIRRJ^2RKR/RL RM lltJRN RO ltKRP RQ ltLRR RS ltMRT RU ltNR# )Wuc  Profile-local durable audit ledger for cron execution attempts.

The ledger records what is known about each attempt; it is not a retry queue. Interrupted attempts
become ``unknown`` only after their owner process is proved gone â€” a start-time reading that fails
to match the claim-time fingerprint is not proof of death. Terminal states are immutable.
)ÚannotationsN)Úcontextmanager)Údatetime)ÚPath)ÚAnyÚDictÚIteratorÚListÚOptional)Úget_hermes_home)Únow)ÚCLAIM_TTL_INACTIVITY_HEADROOM)Úrecord_cron_finishzOptional[Path]ÚEXECUTIONS_FILEiè  g      >@g      ¼@c               ó   € V ^8„  d   QhRR/# )é   Úreturnúsqlite3.Connection© )Úformats   "ÚCC:\Users\johnn\AppData\Local\hermes\hermes-agent\cron\executions.pyÚ__annotate__r   ,   s   € ÷ 	nñ 	nÐ$ñ 	nó    c                 óÆ   € ^ RI Hp  ^ RIHp \        ;'       g'    \        4       P                  4       R,          R,          pV ! VP                  4       V! VRR\        R7      # )é    )Ú_ensure_cron_dir)Úopen_dbÚcronzexecutions.dbzcron/executions.dbT)Údb_labelÚsynchronous_fullÚ
initialize)	Ú	cron.jobsr   Úhermes_cli.sqlite_utilr   r   r   ÚresolveÚparentÚ_initialize_schema)r   r   Úpaths      r   Ú_connectr'   ,   sL   € õ +Ý.ä×VÐVœÓ0×8Ñ8Ó:¸VÕCÀoÕU€DÙ�T—[‘[Ô!Ù�4Ð"6ÈÔZlÔmÐmr   c               ó    € V ^8„  d   QhRRRR/# ©r   Úconnr   r   ÚNoner   )r   s   "r   r   r   8   s   € ÷ *ñ *Ð/ð *°Dñ *r   c                ó  € ^ RI Hp V P                  R4       V! V RRR4       V! V RRR4       V P                  R4       V P                  R	4       V! V RR
R4       V! V RRR4       V! V RRR4       V P                  R4       R# )r   )Úadd_column_if_missingab  CREATE TABLE IF NOT EXISTS executions (
             id TEXT PRIMARY KEY,
             job_id TEXT NOT NULL,
             source TEXT NOT NULL,
             process_id TEXT NOT NULL,
             pid INTEGER NOT NULL,
             process_started_at INTEGER,
             status TEXT NOT NULL CHECK(status IN
               ('claimed','running','completed','failed','unknown')),
             handoff_pending INTEGER NOT NULL DEFAULT 0,
             handoff_started_at REAL,
             claimed_at TEXT NOT NULL,
             started_at TEXT,
             finished_at TEXT,
             error TEXT
           )Ú
executionsÚhandoff_pendingz*handoff_pending INTEGER NOT NULL DEFAULT 0Úhandoff_started_atzhandoff_started_at REALzeCREATE INDEX IF NOT EXISTS idx_executions_job_claimed ON executions(job_id, claimed_at DESC, id DESC)zhCREATE INDEX IF NOT EXISTS idx_executions_status_claimed ON executions(status, claimed_at DESC, id DESC)Údelivery_outcomezdelivery_outcome TEXTÚscheduled_instantzscheduled_instant TEXTÚprogress_atzprogress_at TEXTzvCREATE INDEX IF NOT EXISTS idx_executions_occurrence ON executions(job_id, scheduled_instant) WHERE status='completed'N)r"   r-   Úexecute)r*   r-   s   & r   r%   r%   8   s©   € Ý<à‡L�Lð	ôñ$ ØˆlÐ-Ø4ôñ ØˆlÐ0Ð2Kôð 	‡L�Lð	:ôð 	‡L�Lð	:ôñ ˜$ Ð.@ÐBYÔZÙ˜$ Ð.AÐC[Ô\Ù˜$ ¨mÐ=OÔPØ‡L�Lð	Lör   c               ó   € V ^8„  d   QhRR/# )r   r   zIterator[sqlite3.Connection]r   )r   s   "r   r   r   f   s   € ÷ ñ Ð2ñ r   c            	   #  óà   "  € ^ RI Hp  \        ;_uu_ 4        V ! \        4       4      ;_uu_ 4       pVx € RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i5i)r   )ÚtransactionN)r"   r7   Ú_lockr'   )r7   r*   s     r   Ú_transactionr9   e   s6   é € å2ç	Ž‘œH›J×'Ô'¨4ØŠ
÷ (�‰×'×'ú��ˆüs1   ‚A.—A°A	µA½
A.ÁAÁAÁA+	Á%	A.c               ó$   € V ^8„  d   QhRRRRRR/# )r   r*   r   Úexecution_idÚstrr   úOptional[dict[str, Any]]r   )r   s   "r   r   r   m   s#   € ÷ 2ñ 2Ð#ð 2°3ð 2Ð;Sñ 2r   c                óf   € V P                  R V34      P                  4       pVe   \        V4      # R# )ú#SELECT * FROM executions WHERE id=?N)r4   ÚfetchoneÚdict)r*   r;   Úrows   && r   Ú_fetchrC   m   s1   € Ø
�,‰,Ð<¸|¸oÓ
N×
WÑ
WÓ
Y€CØšŒ4�‹9Ð1¨TÐ1r   r1   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úrecordr=   r1   úOptional[str]r   r+   r   )r   s   "r   r   r   r   s$   € ÷ 	ñ 	Ø$ð	Ø;Hð	à	ñ	r   c               óJ   €  ^ RI Hp V! WR7       R#   \         d     R# i ; i)zFProject durable state to monitoring without affecting ledger behavior.)Úemit_execution_state©r1   N)Úagent.monitoring.cron_healthrH   Ú	Exception)rE   r1   rH   s   &$ r   Ú_emit_execution_staterL   r   s$   € ðÝEá˜V×GøÜô Úðús   ‚ “"¡"c               ó    € V ^8„  d   QhRRRR/# )r   ÚpidÚintr   úOptional[int]r   )r   s   "r   r   r   ~   s   € ÷ ñ ˜Sð  ]ñ r   c                óD   €  ^ RI Hp V! V 4      #   \         d     R# i ; i)r   )Úget_process_start_timeN)Úgateway.statusrR   rK   )rN   rR   s   & r   Ú_process_start_timerT   ~   s'   € ðÝ9Ù% cÓ*Ð*øÜô Úðús   ‚ �žc               ó$   € V ^8„  d   QhRRRRRR/# )r   rN   rO   Ú
started_atrP   r   Úboolr   )r   s   "r   r   r   †   s!   € ÷ >ñ >˜ð >¨ð >¸4ñ >r   c                óÌ   €  ^ RI Hp V! V 4      '       g   R#  Tf   T \        P                  ! 4       8H  # \        T 4      pTf   R# ^ RI Hp T! Y4      #   \         d     R# i ; i)r   )Ú_pid_existsFT)Ústart_time_fingerprints_match)rS   rY   rK   ÚosÚgetpidrT   rZ   )rN   rV   rY   ÚcurrentrZ   s   &&   r   Ú_owner_is_liver^   †   sl   € ðÝ.Ù˜3×ÒÙð  ð ÒØ”b—i’i“kÑ!Ð!Ü! #Ó&€GØ‚Ùõ =Ù(¨Ó=Ð=øô ô Úðús   ‚A ÁA#Á"A#c               ó   € V ^8„  d   QhRR/# )r   r   zOptional[float]r   )r   s   "r   r   r   ˜   s   € ÷ ñ ¨ñ r   c                 óØ   € ^ RI Hp  ^ RIHp \	        V ! 4       4      p\
        P                  ! V4      '       d   V^ 8:  d   R# \        V\        ,          \	        V! 4       4      \        4      # )u‰  Age past which a claimed/running row with a LIVE owner is treated as wedged.

Derived from the existing knobs, never a bare wall-clock constant:
``max(3 Ã— HERMES_CRON_TIMEOUT, cron script timeout, 7200)``. Returns ``None`` (never reclaim
live owners â€” today's behaviour) when the inactivity timeout is 0/unlimited or not a finite
positive number: with no bound to derive from, fail closed.
)Ú_cron_inactivity_seconds)Ú_get_script_timeoutN)
Úcron.schedulerra   Úcron.scheduler_scriptrb   ÚfloatÚmathÚisfiniteÚmaxr   Ú$LIVE_OWNER_STALE_CLAIM_FLOOR_SECONDS)ra   rb   Ú
inactivitys      r   Ú_live_owner_stale_after_secondsrk   ˜   sU   € õ 8Ý9äÑ/Ó1Ó2€JÜ�=Š=˜×$Ò$¨
°a¬ÙÜØÔ2Õ2ÜÑ!Ó#Ó$Ü,óð r   c               ó    € V ^8„  d   QhRRRR/# )r   Ú
claimed_atr<   r   re   r   )r   s   "r   r   r   ­   s   € ÷ Pñ P 3ð P¨5ñ Pr   c                óh   € \        4       \        P                  ! V 4      ,
          P                  4       # )zZSeconds since ``claimed_at`` (NOT NULL, always the aware ISO string from hermes_time.now).)Ú_hermes_nowr   ÚfromisoformatÚtotal_seconds)rm   s   &r   Ú_claim_age_secondsrr   ­   s#   € ä‹MœH×2Ò2°:Ó>Õ>×MÑMÓOÐOr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rm   r<   r3   rF   r   re   r   )r   s   "r   r   r   ²   s!   € ÷ 9ñ 9 3ð 9°]ð 9Àuñ 9r   c                ó,   € \        T;'       g    T 4      # )a/  Seconds since the owner last proved it was making progress.

A wedged worker (#115692) stops stamping ``progress_at``; a long but healthy run keeps
stamping it, so the derived stale bound measures silence, not run length. Rows written
before the column existed have no stamp and fall back to claim age.
)rr   )rm   r3   s   &&r   Ú_stale_age_secondsru   ²   s   € ô ˜k×7Ð7¨ZÓ8Ð8r   c               ó    € V ^8„  d   QhRRRR/# )r   r;   r<   r   rW   r   )r   s   "r   r   r   ¼   s   € ÷ 
!ñ 
!¨3ð 
!°4ñ 
!r   c           
     ó
  € \        4       P                  4       p\        4       ;_uu_ 4       pVP                  RW\        \
        P                  ! 4       34      pVP                  ^8H  uuRRR4       #   + '       g   i     R# ; i)z¯Stamp ``progress_at`` on a running attempt this process owns. Returns False when the row
is no longer ours or no longer running (the caller treats that as informational only).z|UPDATE executions SET progress_at=?
               WHERE id=? AND status IN ('claimed','running') AND process_id=? AND pid=?N)ro   Ú	isoformatr9   r4   Ú_PROCESS_IDr[   r\   Úrowcount)r;   r   r*   Úcurs   &   r   Útouch_execution_progressr|   ¼   s[   € ô ‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lð\à¤¬R¯YªY«[Ð9ó
ˆð
 �|‰|˜qÑ ÷ 
��‹ús   «;A1Á1B	c               ó    € V ^8„  d   QhRRRR/# r)   r   )r   s   "r   r   r   É   s   € ÷ 	ñ 	Ð,ð 	°ñ 	r   c           	     óZ   € V P                  R \        ^ \        \        4      4      34       R# )a8  DELETE FROM executions WHERE id IN (
             SELECT id FROM executions
             WHERE status IN ('completed','failed','unknown')
             ORDER BY julianday(finished_at) DESC, finished_at DESC,
                      julianday(claimed_at) DESC, claimed_at DESC, id DESC LIMIT -1 OFFSET ?
           )N)r4   rh   rO   ÚMAX_TERMINAL_EXECUTIONS)r*   s   &r   Ú_prune_unlockedr€   É   s(   € Ø‡L�Lð	ô 
ˆQ”Ô+Ó,Ó	-Ð/ör   r2   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Újob_idr<   Úsourcer2   rF   r   zdict[str, Any]r   )r   s   "r   r   r   Õ   s,   € ÷ ñ ØðØðØ4Aðàñr   c               ó®  € ^ RI Hp \        4       P                  4       p\        P
                  ! 4       P                  p\        P                  ! 4       p\        4       ;_uu_ 4       pVP                  RV\        V 4      \        V4      \        V\        V4      WC! V4      34       \        Wu4      pRRR4       \        X4       V#   + '       g   i     L; i)z<Persist a claimed attempt before executor/provider dispatch.©r2   zÐINSERT INTO executions
               (id, job_id, source, process_id, pid, process_started_at,
                status, claimed_at, scheduled_instant)
               VALUES (?, ?, ?, ?, ?, ?, 'claimed', ?, ?)N)Úcron.occurrencesr2   ro   rx   ÚuuidÚuuid4Úhexr[   r\   r9   r4   r<   ry   rT   rC   rL   )	r‚   rƒ   r2   Úcanonical_instantr   r;   rN   r*   rE   s	   &$$      r   Úcreate_executionr‹   Õ   s¤   € õ Hä
‹-×
!Ñ
!Ó
#€CÜ—:’:“<×#Ñ#€LÜ
�)Š)‹+€CÜ	�Œ˜4Ø�‰ð=ð œ3˜v›;¬¨F«´[À#Ü  Ó% sÐ,=Ð>OÓ,PðRô	
ô ˜Ó+ˆ÷ 
ô ˜&Ô!Ø€M÷ 
�ús   Á%A
CÃC	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   r<   ÚinstantrF   r   r+   r   )r   s   "r   r   r   ì   s&   € ÷ Uñ U¨3ð U¸ð UÈ4ñ Ur   c           
     ó  € ^ RI Hp \        4       ;_uu_ 4       pVP                  RV! V4      V \        \
        P                  ! 4       34      pVP                  ^8w  d   \        R4      h RRR4       R#   + '       g   i     R# ; i)zGBind the store-claimed snapshot before a provider hands it to a worker.r…   zzUPDATE executions SET scheduled_instant=? WHERE id=? AND status='claimed' AND handoff_pending=0 AND process_id=? AND pid=?z2Cron occurrence could not be bound before dispatchN)	r†   r2   r9   r4   ry   r[   r\   rz   ÚRuntimeError)r;   r�   r2   r*   r{   s   &&   r   Úset_execution_occurrencer�   ì   sc   € å2ä	�Œ˜4Ø�l‰lð?á˜wÓ'¨´{ÄBÇIÂIÃKÐPó
ˆð
 �<‰<˜1ÔÜÐSÓTÐTð ÷ 
��Šús   ™AA4Á4B	c               ó    € V ^8„  d   QhRRRR/# ©r   r;   r<   r   r=   r   )r   s   "r   r   r   ú   s   € ÷ ñ °ð Ð9Qñ r   c           
     óF  € \        4       ;_uu_ 4       pVP                  R\        P                  ! 4       V \        \        P
                  ! 4       34      pVP                  ^8w  d    RRR4       R# \        W4      pRRR4       \        X4       V#   + '       g   i     L; i)zDFence restart recovery while an external worker is adopting a claim.z§UPDATE executions
               SET handoff_pending=1, handoff_started_at=?
               WHERE id=? AND status='claimed'
                 AND process_id=? AND pid=?N)	r9   r4   Útimery   r[   r\   rz   rC   rL   )r;   r*   r{   rE   s   &   r   Úmark_execution_handoff_pendingr•   ú   sx   € ä	�Œ˜4Ø�l‰lð/ô �YŠY‹[˜,¬´R·Y²Y³[ÐAó
ˆð �<‰<˜1ÔØ÷ 
‰ô ˜Ó+ˆ÷ 
ô ˜&Ô!Ø€M÷ 
�ús   “ABÁ0BÂB 	c               ó    € V ^8„  d   QhRRRR/# r’   r   )r   s   "r   r   r     s   € ÷ ñ ¨#ð Ð2Jñ r   c           
     óh  € \         P                  ! 4       p\        V4      p\        4       P	                  4       p\        4       ;_uu_ 4       pVP                  R\        WW034      pVP                  ^8w  d    RRR4       R# \        W@4      pRRR4       \        X4       V#   + '       g   i     L; i)u	  Atomically transfer and start an attempt in its worker process.

The dispatching gateway creates the row before spawning a restart-safe
worker.  Adoption is the single ``claimed`` â†’ ``running`` gate: only the
winner may acknowledge ownership or run side effects.
a  UPDATE executions
               SET process_id=?, pid=?, process_started_at=?,
                   status='running', started_at=?, handoff_pending=0,
                   handoff_started_at=NULL
               WHERE id=? AND status='claimed' AND handoff_pending=1N)r[   r\   rT   ro   rx   r9   r4   ry   rz   rC   rL   )r;   rN   Úprocess_started_atr   r*   r{   rE   s   &      r   Úadopt_claimed_executionr™     s“   € ô �)Š)‹+€CÜ,¨SÓ1ÐÜ
‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lðHô
 ˜#°3ÐEó
ˆð �<‰<˜1ÔØ÷ 
‰ô ˜Ó+ˆ÷ 
ô ˜&Ô!Ø€M÷ 
�ús   Á,B!ÂB!Â!B1	c               ó    € V ^8„  d   QhRRRR/# r’   r   )r   s   "r   r   r   %  s   € ÷ ñ ¨ð Ð1Iñ r   c           
     óN  € \        4       P                  4       p\        4       ;_uu_ 4       pVP                  RW\        \
        P                  ! 4       34      pVP                  ^8w  d    RRR4       R# \        W 4      pRRR4       \        X4       V#   + '       g   i     L; i)z7Transition one claimed attempt to running exactly once.zóUPDATE executions
               SET status='running', started_at=?, handoff_pending=0,
                   handoff_started_at=NULL
               WHERE id=? AND status='claimed' AND handoff_pending=0
                 AND process_id=? AND pid=?N)
ro   rx   r9   r4   ry   r[   r\   rz   rC   rL   )r;   r   r*   r{   rE   s   &    r   Úmark_execution_runningrœ   %  s€   € ä
‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lð/ð
 ¤¬R¯YªY«[Ð9ó
ˆð �<‰<˜1ÔØ÷ 
‰ô ˜Ó+ˆ÷ 
ô ˜&Ô!Ø€M÷ 
�ús   «?BÁ4BÂB$	Úerrorc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   r;   r<   ÚsuccessrW   r�   rF   r1   r   r=   r   )r   s   "r   r   r   8  s6   € ÷ ñ ØðØ#'ðØ0=ðà#ðð ñr   c          
     óâ  € \        4       P                  4       pV'       d   RMRpV'       d   RMV'       d   \        V4      MRp\        4       ;_uu_ 4       p\        \
        P                  ! 4       3pVP                  RWTWcV .VO54      p	V	P                  ^8w  d    RRR4       R# \        V4       \        Wp4      p
RRR4       \        X
VR7       \        W£4       V
#   + '       g   i     L*; i)zÍWrite a terminal result once; terminal attempts cannot be rewritten.

Only the owning process may finish its attempt; receipt recovery for a departed owner
settles through ``recover_receipted_execution``.
Ú	completedÚfailedNúunknown failurea  UPDATE executions
               SET status=?, finished_at=?, error=?, handoff_pending=0,
                   handoff_started_at=NULL, delivery_outcome=?
               WHERE id=? AND status IN ('claimed','running')
                 AND process_id=? AND pid=?rI   )ro   rx   r<   r9   ry   r[   r\   r4   rz   r€   rC   rL   r   )r;   rŸ   r�   r1   r   ÚstatusÚdetailr*   Úownerr{   rE   s   &$$$       r   Úfinish_executionr§   8  s¿   € ô ‹-×
!Ñ
!Ó
#€Cß#‰[¨€Fß‰T·¤3 u¤:Ð<M€FÜ	�Œ˜4ÜœbŸiši›kÐ*ˆØ�l‰lð/ð
 ˜&°LÐIÀ5ÑIó
ˆð �<‰<˜1ÔØ÷ 
‰ô 	˜ÔÜ˜Ó+ˆ÷ 
ô ˜&Ð3CÕDÜ�vÔ0Ø€M÷! 
�ús   ÁACÂ&CÃC.	c          
     ó¾  € \        4       P                  4       p\        4       ;_uu_ 4       p\        W`V4      pVe   \	        V4      '       d    RRR4       R# TP                  RV'       d   RMRYR'       d   RMV'       d   \        V4      MRW@34       \        V4       \        W`4      pRRR4       \        XVR7       \        W„4       V#   + '       g   i     L*; i)z¾Settle a verified canonical receipt after owner loss, including its unknown audit row.

Terminal verdicts stay immutable. A live firer still owns its bookkeeping
(``execution_owner_live``).
Nz�UPDATE executions SET status=?, finished_at=?, error=?, handoff_pending=0,
               handoff_started_at=NULL, delivery_outcome=? WHERE id=?r¡   r¢   r£   rI   )ro   rx   r9   Ú_recoverable_rowÚ_row_owner_liver4   r<   r€   rC   rL   r   )	r;   r‚   rŸ   r�   r1   r   r*   rB   rE   s	   &&$$$    r   Úrecover_receipted_executionr«   W  s³   € ô ‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ü˜t°6Ó:ˆØŠ;œ/¨#×.Ò.Ø÷ 
‰ð 	�‰ðIç#‰[¨°3Æ¹×\aÌcÐRWÌjÐgxØð-ô	.ô
 	˜ÔÜ˜Ó+ˆ÷ 
ô ˜&Ð3CÕDÜ�vÔ0Ø€M÷ 
�ús   «#CÁCÁ,CÂ)CÃC	c                ój   € V P                  R \        V4      \        V4      34      P                  4       # )z“SELECT status, process_id, pid, process_started_at FROM executions
           WHERE id=? AND job_id=? AND status IN ('claimed','running','unknown'))r4   r<   r@   )r*   r;   r‚   s   &&&r   r©   r©   n  s3   € Ø�<‰<ð	Tä	ˆ\Ó	œC ›KÐ(ó*÷ +3©(«*ð5r   c               ó   € V ^8„  d   QhRR/# )r   r   rW   r   )r   s   "r   r   r   u  s   € ÷ Fñ F˜Dñ Fr   c                ó„   € V R ,          \         8X  d   V R,          R8g  # \        \        V R,          4      V R,          4      # )Ú
process_idr¤   ÚunknownrN   r˜   )ry   r^   rO   )rB   s   &r   rª   rª   u  s;   € Ø
ˆ<ÕœKÔ'ð �8�} 	Ñ)Ð)Üœ#˜c %�j›/¨3Ð/CÕ+DÓEÐEr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   r<   r‚   r   rW   r   )r   s   "r   r   r   }  s!   € ÷ 4ñ 4 sð 4°Cð 4¸Dñ 4r   c                ó¤   € \        4       ;_uu_ 4       p\        W V4      pRRR4       XRJ;'       d    \        V4      #   + '       g   i     L'; i)z©True while the attempt's own firer (this process included) can still finish it, so receipt
recovery must not act for it: no output re-save, no job mark, no ledger write.N)r9   r©   rª   )r;   r‚   r*   rB   s   &&  r   Úexecution_owner_liver³   }  s=   € ô 
�Œ˜4Ü˜t°6Ó:ˆ÷ 
à�dˆ?×3Ð3œ¨sÓ3Ð3÷ 
�ús	   “?¿A	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   r<   Úoutcomer   rW   r   )r   s   "r   r   r   …  s!   € ÷ ñ ¨#ð ¸ð Àñ r   c                ó¢   € \        4       ;_uu_ 4       pVP                  RW34      pRRR4       XP                  ^8H  #   + '       g   i     L; i)züReplace a terminal attempt's ``queued`` delivery outcome with the drain's real one.

The only post-terminal rewrite the ledger allows: the attempt's status is untouched and
only a ``queued`` handoff can settle, so a replay or a late caller is a no-op.
z UPDATE executions SET delivery_outcome=?
               WHERE id=? AND delivery_outcome='queued'
                 AND status IN ('completed','failed','unknown')N)r9   r4   rz   )r;   rµ   r*   r{   s   &&  r   Úsettle_delivery_outcomer·   …  sG   € ô 
�Œ˜4Ø�l‰lðCð Ð#ó	
ˆ÷ 
ð �<‰<˜1ÑÐ÷ 
�ús	   “>¾A	z}Scheduler restarted after this execution's owner exited before a durable terminal state; whether side effects ran is unknown.z®Owner process is still alive but the claim outlived the derived stale bound; treated as wedged (#115692). The process was not terminated; whether side effects ran is unknown.c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r;   r<   r‚   r�   r   r+   r   )r   s   "r   r   r      s(   € ÷ >ñ >¨Sð >¸#ð >Àcð >Èdñ >r   c                ó¤   €  \        V RVR7       R#   \        P                  \        3 d#   p\        P                  RYY#4        Rp?R# Rp?ii ; i)z¤Close the receipt of a run that never started: a ``claimed`` row never resolves. Best-effort
so a ledger write cannot mask the failure the caller logs or re-raises.F)rŸ   r�   z7Job '%s': failed to close execution receipt %s (%s): %sN)r§   Úsqlite3ÚErrorÚOSErrorÚloggerr�   )r;   r‚   r�   Ú
record_errs   &&& r   Úsettle_unstarted_executionr¿      sE   € ð>Ü˜¨u¸E×BøÜ�M‰Mœ7Ð#ô >Ü�‰ÐNØ¨5÷	>ò 	>ûð>ús   ‚ ’A­A
Á
Ac               ó   € V ^8„  d   QhRR/# )r   r   rO   r   )r   s   "r   r   r   ª  s   € ÷ Iñ I¨ñ Ir   c                 ó(  € \        4       P                  4       p ^ p. pRpRp\        4       ;_uu_ 4       pVP                  R4      P	                  4       pV EFv  pVR,          \
        8X  d   K  \        p\        \        VR,          4      VR,          4      '       d@   V'       g   \        4       pRpVe    \        VR,          VR	,          4      V8:  d   K€  \        pVR
,          p	VR,          '       d5   V	e1   \        P                  ! 4       \        V	4      ,
          \        8  d   KÒ  VP                  RWVR,          VR,          VR,          VR,          VR,          VR
,          VR,          VR	,          3
4      p
WP                  ,          pV
P                  '       g   EKL  \!        WWR,          4      pVf   EKe  VP#                  V4       EKy  	  V'       d   \%        V4       RRR4       V F  p\'        V4       K  	  V#   + '       g   i     L&; i)zÇMark abandoned attempts unknown without scheduling retries: rows whose owner is provably
dead, plus rows whose live owner holds a claim older than the derived stale bound (the
process is not killed).NFzÞSELECT id, status, process_id, pid, process_started_at,
                      handoff_pending, handoff_started_at, claimed_at, progress_at
               FROM executions
               WHERE status IN ('claimed','running')r¯   rN   r˜   Trm   r3   r0   r/   aq  UPDATE executions
                   SET status='unknown', finished_at=?, error=?,
                       handoff_pending=0, handoff_started_at=NULL
                   WHERE id=? AND status=? AND process_id=? AND pid=?
                     AND handoff_pending=?
                     AND handoff_started_at IS ?
                     AND claimed_at=? AND progress_at IS ?Úidr¤   )ro   rx   r9   r4   Úfetchallry   Ú_OWNER_GONE_REASONr^   rO   rk   ru   Ú_OWNER_WEDGED_REASONr”   re   ÚHANDOFF_ADOPTION_GRACE_SECONDSrz   rC   Úappendr€   rL   )r   ÚchangedÚ	recoveredÚstale_afterÚstale_after_resolvedr*   ÚrowsrB   Úreasonr0   r{   rE   s               r   Úrecover_interrupted_executionsrÎ   ª  sÒ  € ô ‹-×
!Ñ
!Ó
#€CØ€GØ&(€Ið $(€KØ ÐÜ	�Œ˜4Ø�|‰|ð8ó
÷
 ‰(‹*ð 	ô ˆCØ�<Õ ¤KÔ/ÙÜ'ˆFÜœc # e¥*›o¨sÐ3GÕ/H×IÒI÷ ,Ü"AÓ"C�KØ+/Ð(àÒ'Ü)¨#¨lÕ*;¸SÀÕ=OÓPÐT_Ô_áÜ-�Ø!$Ð%9Õ!:ÐàÐ%×&Ô&Ø&Ò2Ü—I’I“K¤%Ð(:Ó";Õ;Ü0ô1ñ ð —,‘,ð>ð ˜c $�i¨¨X­¸¸LÕ8IÈ3ÈuÍ:ØÐ&Õ'¨Ð-AÕ)BØ�\Õ" C¨Õ$6ð8óˆCð —|‘|Õ#ˆGØ�|�|‹|Ü ¨$¥iÓ0�ØÕ%Ø×$Ñ$ V×,ñe ÷f Ü˜DÔ!÷w 
óx ˆÜ˜fÖ%ñ à€N÷} 
�ús,   ³A0HÂ$AHÃ3B(HÆ!HÆ:HÇHÈH	c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r;   r<   rÍ   r   rW   r   )r   s   "r   r   r   ö  s!   € ÷ 4ñ 4¨ð 4¸ð 4Àñ 4r   c               ó:  € \        4       P                  4       p\        4       ;_uu_ 4       pVP                  RV 34      P	                  4       pVe   VR,          R9  d    RRR4       R# VR,          \
        8X  d    RRR4       R# \        \        VR,          4      VR,          4      '       d    RRR4       R# VR,          pVR	,          '       d>   Ve:   \        P                  ! 4       \        V4      ,
          \        8  d    RRR4       R# VP                  R
W!VR,          VR,          VR,          VR,          34      pVP                  ^8w  d    RRR4       R# \        W04      p\        V4       RRR4       \        X4       R#   + '       g   i     L; i)ui  Record one attempt as ``unknown`` with a cause this process actually observed.

``recover_interrupted_executions`` sweeps every attempt whose owner is provably
dead, and knows nothing but that absence â€” so all it can write is
``_OWNER_GONE_REASON``, which asserts a scheduler restart. A waiter that held the
worker's ``Popen`` knows more: the owner was that external worker, and it exited
with a known status. Without this, a manual run whose worker dies is filed as
"Scheduler restarted ..." (a restart that never happened) and, because the sweep
leaves the row terminal, the waiter reports success and never records the run â€”
the job's ``fire_claim`` then blocks the next manual fire for the whole lease
(#128509).

The attempt stays ``unknown``, not ``failed``: whether side effects ran is still
unknown. Only the CAUSE becomes truthful. Returns False â€” leaving the caller to
fall back to the generic sweep â€” when the row is absent, already terminal, owned by
this process, inside the handoff adoption grace, or owned by a live process: a
worker that is still running must never be terminalized out from under itself.
z›SELECT id, status, process_id, pid, process_started_at,
                      handoff_pending, handoff_started_at
               FROM executions WHERE id=?Nr¤   Fr¯   rN   r˜   r0   r/   zÎUPDATE executions
               SET status='unknown', finished_at=?, error=?,
                   handoff_pending=0, handoff_started_at=NULL
               WHERE id=? AND status=? AND process_id=? AND pid=?rÂ   T©ÚclaimedÚrunning)ro   rx   r9   r4   r@   ry   r^   rO   r”   re   rÆ   rz   rC   r€   rL   )r;   rÍ   r   r*   rB   r0   r{   rE   s   &$      r   Úterminalize_dead_ownerrÕ   ö  sb  € ô& ‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lð-ð ˆOó	
÷
 ‰(‹*ð 	ð Š;˜#˜h�-Ð/EÔEØ÷ 
‰ð ˆ|Õ¤Ô+Ø÷ 
‰ô œ#˜c %�j›/¨3Ð/CÕ+D×EÒEØ÷ 
‰ð !Ð!5Õ6ÐàÐ!×"Ô"Ø"Ò.Ü—	’	“œeÐ$6Ó7Õ7Ô:XÔXà÷' 
‰ð( �l‰lðEð ˜#˜d�) S¨¥]°C¸Õ4EÀsÈ5ÅzÐRó
ˆð �<‰<˜1ÔØ÷9 
‰ô: ˜Ó+ˆÜ˜Ô÷= 
ô> ˜&Ô!Ù÷A 
�ús0   «5F
Á*F
Â*F
Â;F
Ã3F
ÄAF
ÅF
Æ
F	c               ó$   € V ^8„  d   QhRRRRRR/# rÐ   r   )r   s   "r   r   r   -  s!   € ÷ ñ  Cð °Cð ¸Dñ r   c               óŒ  € \        4       P                  4       p\        4       ;_uu_ 4       pVP                  RW!\	        V 4      \
        \        P                  ! 4       34      pVP                  ^8w  d    RRR4       R# \        V\	        V 4      4      p\        V4       RRR4       \        X4       R#   + '       g   i     L; i)a]  The firer itself gave up on its in-flight attempt (``CronExecutionUnknown``): record it
``unknown`` now, owner-fenced to this process, instead of leaving it ``running`` until a
restart's dead-owner sweep. Receipt recovery never acts for a same-process running row, so
the owner's later terminal receipt can settle it only once it is marked given up.zÖUPDATE executions SET status='unknown', finished_at=?, error=?,
                   handoff_pending=0, handoff_started_at=NULL
               WHERE id=? AND status IN ('claimed','running') AND process_id=? AND pid=?NFT)ro   rx   r9   r4   r<   ry   r[   r\   rz   rC   r€   rL   )r;   rÍ   r   r*   r{   rE   s   &$    r   Úgive_up_executionrØ   -  s˜   € ô
 ‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lð\ð œ#˜lÓ+¬[¼"¿)º)»+ÐFó	Hˆð
 �<‰<˜1ÔØ÷ 
‰ô ˜œc ,Ó/Ó0ˆÜ˜Ô÷ 
ô ˜&Ô!Ù÷ 
�ús   «A	B3Á> B3Â3C	r‚   ÚlimitÚbefore_claimed_atc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r‚   rF   rÙ   rO   rÚ   r   zlist[dict[str, Any]]r   )r   s   "r   r   r   A  s,   € ÷ 'ñ 'Øð'Ø,/ð'ØIVð'àñ'r   c           
     ón  € . p. pV e,   VP                  R4       VP                  \        V 4      4       Ve4   VP                  R4       VP                  \        V4      .^,          4       V'       d   RRP                  V4      ,           MRpVP                  \	        ^\        \        V4      R4      4      4       \        4       ;_uu_ 4       pVP                  RV,           R	,           V4      P                  4       pRRR4       X Uu. uF  p\        V4      NK  	  up#   + '       g   i     L+; iu upi )
zFReturn indexed, newest-first execution history with cursor pagination.Nzjob_id=?z7(julianday(claimed_at), claimed_at) < (julianday(?), ?)z WHERE z AND Ú iô  zSELECT * FROM executionszF ORDER BY julianday(claimed_at) DESC, claimed_at DESC, id DESC LIMIT ?)rÇ   r<   ÚextendÚjoinrh   ÚminrO   r9   r4   rÃ   rA   )	r‚   rÙ   rÚ   ÚclausesÚparamsÚwherer*   rÌ   rB   s	   $$$      r   Úlist_executionsrä   A  s÷   € ð €GØ€FØÒØ�‰�zÔ"Ø�‰”c˜&“kÔ"ØÒ$à�‰ÐPÔQØ�‰”sÐ,Ó-Ð.°Õ2Ô3ß18ˆI˜Ÿ™ WÓ-Ö-¸b€EØ
‡M�M”#�aœœS ›Z¨Ó-Ó.Ô/ô 
�Œ˜4Ø�|‰|Ø&¨Õ.ØVõWàó
÷ ‰(‹*ð	 	÷ 
ñ "&Ó&¡˜#ŒD�ŽI¡Ñ&Ð&÷ 
�üò 's   Ã/DÄD2ÄD/	c               ó    € V ^8„  d   QhRRRR/# r’   r   )r   s   "r   r   r   [  s   € ÷ 2ñ 2 ð 2Ð(@ñ 2r   c                óÔ   € \        4       ;_uu_ 4       pVP                  R\        V 4      34      P                  4       pRRR4       Xe   \	        V4      # R#   + '       g   i     L!; i)zBReturn one exact execution attempt, or ``None`` when it is absent.r?   N)r9   r4   r<   r@   rA   )r;   r*   rB   s   &  r   Úget_executionrç   [  sU   € ä	�Œ˜4Ø�l‰lØ1Ü�ÓÐ ó
÷ ‰(‹*ð 	÷ 
ð
 šŒ4�‹9Ð1¨TÐ1÷ 
�ús   “+AÁA'	c               ó    € V ^8„  d   QhRRRR/# ©r   r‚   r<   r   r=   r   )r   s   "r   r   r   e  s   € ÷ %ñ %˜Sð %Ð%=ñ %r   c                óB   € \        V ^R7      pV'       d
   V^ ,          # R# )é   )r‚   rÙ   N)rä   )r‚   rÌ   s   & r   Úlatest_executionrì   e  s   € Ü &°Ô2€Dßˆ4��7Ð$ Ð$r   c               ó    € V ^8„  d   QhRRRR/# ré   r   )r   s   "r   r   r   j  s   € ÷ ñ  Cð Ð,Dñ r   c                óÂ   € \        V 4      pV'       d   VP                  R4      R9  d   R# \        \        VR,          4      VP                  R4      4      '       g   R# V# )ue  The job's latest attempt while it is still claimed/running under a LIVE owner, else ``None``.

This is scheduler OWNERSHIP, not recent activity: a run inside a long tool call writes no
heartbeat yet stays owned, while a run whose process died (watchdog kill, crash) does not.
Read-only â€” unlike ``recover_interrupted_executions`` it never rewrites a row.
r¤   NrN   r˜   rÒ   )rì   Úgetr^   rO   )r‚   rE   s   & r   Úlive_inflight_executionrð   j  sM   € ô ˜fÓ%€Fß�V—Z‘Z Ó)Ð1GÔGÙÜœ#˜f U�mÓ,¨f¯j©jÐ9MÓ.N×OÒOÙØ€Mr   c               ó    € V ^8„  d   QhRRRR/# )r   Újob_idsz	list[str]r   zdict[str, dict[str, Any]]r   )r   s   "r   r   r   y  s   € ÷ 6ñ 6˜yð 6Ð-Fñ 6r   c                ó®  € \         P                  V 4       Uu. uF  q'       g   K  \        V4      NK  	  ppV'       g   / # RP                  R V 4       4      p\	        4       ;_uu_ 4       pVP                  RV R2V4      P                  4       pRRR4       X Uu/ uF  qfR,          \        V4      bK  	  up# u upi   + '       g   i     L7; iu upi )z1Load latest execution for many jobs in one query.Ú,c              3  ó&   "  € T F  pR x € K	  	  R# 5i)Ú?Nr   )Ú.0Ú_s   & r   Ú	<genexpr>Ú$latest_executions.<locals>.<genexpr>~  s   é € Ð/© A�C«ùs   ‚ag  SELECT e.* FROM executions e WHERE e.id IN (
                  SELECT id FROM (
                    SELECT id, ROW_NUMBER() OVER (
                             PARTITION BY job_id
                             ORDER BY julianday(claimed_at) DESC, claimed_at DESC, id DESC
                           ) AS rn
                    FROM executions WHERE job_id IN (z ))
                  WHERE rn=1)Nr‚   )rA   Úfromkeysr<   rß   r9   r4   rÃ   )rò   r‚   ÚcleanÚplaceholdersr*   rÌ   rB   s   &      r   Úlatest_executionsrþ   y  sÀ   € ä'+§}¡}°WÔ'=ÓHÑ'=˜VÃŒ[ŒS�Ž[Ñ'=€EÐHßØˆ	Ø—8‘8Ñ/©Ó/Ó/€Lô 
�Œ˜4Ø�|‰|ð6ð 7C°^ð Dð!ð ó

÷ ‰(‹*ð 	÷ 
ñ 15Ó5±¨��Mœ4 ›9Ò$±Ñ5Ð5ùò% I÷ 
�üò 6s   ˜	B:¦B:Á+%B?ÂCÂ?C	)r¡   r¢   r°   )OÚ__conditional_annotations__Ú__doc__Ú
__future__r   Úloggingrf   r[   rº   Ú	threadingr”   r‡   Ú
contextlibr   r   Úpathlibr   Útypingr   r   r   r	   r
   Úhermes_constantsr   Úhermes_timer   ro   Úcron.constantsr   Ú/hermes_cli.observability.shared_metrics_gatewayr   Ú	getLoggerÚ__name__r½   r   Ú__annotations__r   rÆ   ri   Ú_TERMINAL_STATESÚRLockr8   rˆ   r‰   ry   r'   r%   r9   rC   rL   rT   r^   rk   rr   ru   r|   r€   r‹   r�   r•   r™   rœ   r§   r«   r©   rª   r³   r·   rÄ   rÅ   r¿   rÎ   rÕ   rØ   rä   rç   rì   rð   rþ   )rÿ   s   @r   Ú<module>r     s£  øðôõ #ã Û Û 	Û Û Û Û Ý %Ý Ý ß 6Õ 6å ,Ý *Ý 8Ý Nà	×	Ò	˜8Ó	$€ð
 #'€�Ó &ØÐ Ø!%Ð à'-Ð $Ø5Ð Ø�ŠÓ€Ø�jŠj‹l×Ñ€õ
	nõ*ðZ ôó ðõ2ð
	ØKO÷	õõ>õ$õ*Põ
9õ
!õ	ðØDH÷õ.Uõõ"õ4ð&Ø@Dðà&*÷ð>Èð Ð_cô ò.5õFõ4õð";ð ð
ð õ>õIõX4õnð('Ø#ð'Ø24ð'ØY]÷'õ42õ%õ
÷6r   