+
    jHàjW‚  ã                  óŒ  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	H
t
 ^ RIHt ^ RIHt ]P                  ! ]4      tR't^
tR R ltR R	 ltR
 tR R ltR R ltR(R R llt]P4                  R 4       t ! R R]	4      tR R ltR R ltR R ltR R lt RRRRRR/R R  llt!R! R" lt"R# R$ lt# ! R% R&]4      t$R# ))u  CronScheduler provider interface (Axis B â€” the trigger). EXPERIMENTAL: shape MAY change until a
second provider validates it; growth MUST be additive (optional method with a default), never a
changed start() signature or new abstractmethod. Providers decide only *when* a job fires â€”
execution + delivery stay in cron.scheduler.run_job / _deliver_result; never reimplement them.
)ÚannotationsN)ÚABCÚabstractmethod)ÚPath)ÚAnyc               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚintervalÚfloatÚconsecutive_failuresÚintÚreturn© )Úformats   "Ú</home/ubuntu/.hermes/hermes-agent/cron/scheduler_provider.pyÚ__annotate__r      s&   € ÷ Yñ Y Eð YÀð YÈñ Yó    c                ó^   € V^ 8:  d   V # \        V ^V^,
          ,          ,          \        4      # )z�Plain ``interval`` while healthy; doubles per fd-exhaustion failure, capped.

Exponential tick backoff shared by both ticker loops (#87644).
)ÚminÚ_EMFILE_BACKOFF_MAX_SECONDS)r	   r   s   &&r   Ú_backoff_wait_secondsr      s/   € ð
 ˜qÔ ØˆÜˆx˜1Ð 4°qÕ 8Õ9Õ:Ô<WÓXÐXr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚexcÚBaseExceptionr   r   r   r   )r   s   "r   r   r   &   s!   € ÷ ñ ˜Mð Àð Èñ r   c                óR   € ^ RI HpHp V! V 4      '       d   V! 4        V^,           # ^ # )uš  On fd exhaustion: reclaim fds and bump the backoff counter; any other failure resets it â€”
backoff is reserved for the EMFILE storm.

Shared by both ticker loops (#87644): on fd exhaustion, attempt reclamation (gc.collect + raise the soft
nofile limit) so the NEXT tick can succeed, and bump the counter so ``_backoff_wait_seconds`` backs off
exponentially while the process has no chance of making progress.
)Ú_is_fd_exhaustionÚ_reclaim_fds_best_effort)Úcron.schedulerr   r   )r   r   r   r   s   &&  r   Ú_note_tick_failurer   &   s'   € ÷ Ká˜×ÒÙ Ô"Ø# aÕ'Ð'Ùr   c                óz   €  V ! V/ VB  R#   \          d$   p\        P                  RYRR7        Rp?R# Rp?ii ; i)u�  Run a ticker status-marker write so a failing store never ends the ticker thread.

The gateway runs the provider on an unsupervised daemon thread: one escaping exception
there stops cron silently while the gateway keeps serving (#111010). Heartbeat/error
markers are diagnostics for ``hermes cron status`` â€” losing one write to a broken store
must degrade to a logged warning, not thread death.
zCron %s write failed: %sT©Úexc_infoN)r   ÚloggerÚwarning)ÚactionÚdescriptionÚargsÚkwargsÚes   &&*, r   Ú_guarded_store_writer)   6   s=   € ðRÙ�Ð˜ÔøÜô RÜ�‰Ð1°;ÈDˆ×QÒQûðRús   ‚ Œ:—5µ:c               ó   € V ^8„  d   QhRR/# )r   r   Útupler   )r   s   "r   r   r   D   s   € ÷ @ñ @˜Uñ @r   c                ó:   € \        V \        4      '       d   V # RV 3# )z^Normalize a ``profile_homes`` entry (``(name, home)`` tuple or bare home) to ``(name,
home)``.N)Ú
isinstancer+   )Úentrys   &r   Ú_profile_entryr/   D   s   € ô ˜u¤e×,Ò,ˆ5Ð?°4¸°-Ð?r   c               ó    € V ^8„  d   QhRRRR/# )r   Úprofile_homesÚlistr   r   )r   s   "r   r   r   J   s   € ÷ Yñ Y¨4ð Y°Dñ Yr   c                ó*  € \        V 4      '       d    \        V ! 4       4      p V  Uu. uF6  p\        \        V4      ^,          4      P                  4       '       g   K4  VNK8  	  up#   \         d    \        P	                  RRR7       . u # i ; iu upi )a6  Drop homes no longer on disk: ticking/heartbeating a deleted home would recreate its
``cron/`` workspace and silently resurrect the profile.

Ticking or heartbeating a deleted home recreates its ``cron/`` workspace (``record_ticker_heartbeat`` ->
``ensure_dirs`` -> ``mkdir(parents=True)``) on every 60s cycle, so the "deleted" profile silently comes
back on disk and in ``hermes profile list`` (#47368). Filtering on directory existence leaves a deleted
profile's home untouched, which is the correct invariant: a home that does not exist cannot hold jobs to
fire.
z4cron profile enumeration failed; skipping this cycleTr    )Úcallabler2   Ú	Exceptionr"   r#   r   r/   Úis_dir)r1   r.   s   & r   Ú_existing_profile_homesr7   J   s€   € ô �×Òð	Ü ¡£Ó1ˆMñ  -ÓX™}�e´´^ÀEÓ5JÈ1Õ5MÓ0N×0UÑ0U×0W�EˆE™}ÑXÐXøô ô 	Ü�N‰NÐQÐ\`ˆNÔaØŠIð	üò Ys   “A& §1BÁBÁ&$BÂBc               ó   € V ^8„  d   QhRR/# ©r   r   Úboolr   )r   s   "r   r   r   _   s   € ÷ Yñ Y dñ Yr   c                ó\   € ^ RI HpHpHp V e   T MV! 4       pV! V4      V! V! 4       4      8g  # )a²  True when a fire runs for a profile OTHER than the process's own.

Derived from the fire's home itself (``home``, else the task's active ``get_hermes_home()``), never from
a marker one entry point sets: the desktop ticker (``_profile_cron_scope``), the dashboard's
manual Run now (``hermes_cli.web_server_cron._cron_store_scope``) and any other caller that
binds a HERMES_HOME override for a sibling profile all reach ``run_one_job`` the same way, and a
marker set only in the ticker left the manual path with the original cross-profile leak.

The desktop backend fires every local profile from one process without setting the
process-global multiplex flag, so every isolation keyed on ``is_multiplex_active()`` was inert
for those fires: a sibling profile's ``.env`` landed in the shared ``os.environ`` with
``override=True`` and a scope miss read the launch profile's credentials (#107692).
``cron.scheduler._install_fire_secret_scope`` turns this into multiplex semantics for exactly
the span the profile's secret scope covers, and the restart-safe handoff marks the worker
payload with it. The launch identity is ``get_routing_process_hermes_home()`` (gateway/AGENTS.md
"One launch-home identity").)Úget_hermes_homeÚget_routing_process_hermes_homeÚhermes_home_key)Úhermes_constantsr<   r=   r>   )Úhomer<   r=   r>   Útargets   &    r   Úrouted_profile_firerB   _   s3   € ÷" cÑbàÒ%‰T©?Ó+<€FÙ˜6Ó"¡oÑ6UÓ6WÓ&XÑXÐXr   c              #  óØ   "  € ^ RI Hp ^ RIHpHp V! \        V 4      4      p V! V 4      ;_uu_ 4        Rx € RRR4       V! V4       R#   + '       g   i     L; i  T! T4       i ; i5i)zJScope the calling thread to one profile's home + cron store for the block.)Úuse_cron_store)Úset_hermes_home_overrideÚreset_hermes_home_overrideN)Ú	cron.jobsrD   r?   rE   rF   Ústr)r@   rD   rE   rF   Ú
home_tokens   &    r   Ú_profile_cron_scoperJ   v   sR   é € õ )ßUñ *¬#¨d«)Ó4€Jð/Ù˜D×!Õ!Û÷ "ñ 	# :Ö.÷ "×!ûñ 	# :Õ.üs2   ‚ A*£A ³A
¸A Á 
A*Á
A	ÁA Á
A'Á'A*c                  ó  € ] tR t^ˆtRt]]R R l4       4       tR R lt]RRRRR	^</R
 R ll4       t	R R lt
R R ltR R ltR R lt]R R l4       tRRRRRRRR/R R lltRRRR/R R lltRRRRRR/R R lltR  R! ltR"tR# )#ÚCronSchedulerz§Decides WHEN a due cron job fires. Only ``name`` + ``start`` are required; keep every other
hook NON-abstract with a safe default (``test_abc_growth_stays_additive``).c               ó   € V ^8„  d   QhRR/# ©r   r   rH   r   )r   s   "r   r   ÚCronScheduler.__annotate__Ž   s   € ÷ ;ñ ;�cñ ;r   c                ó   € R# )z,Short identifier, e.g. 'builtin', 'chronos'.Nr   ©Úselfs   &r   ÚnameÚCronScheduler.nameŒ   ó   ‚ r   c               ó   € V ^8„  d   QhRR/# r9   r   )r   s   "r   r   rO   ‘   s   € ÷ ñ ˜dñ r   c                ó   € R# )uT   Whether this provider can run here. MUST NOT make network calls; False â†’ built-in.Tr   rQ   s   &r   Úis_availableÚCronScheduler.is_available‘   s   € ár   ÚadaptersNÚloopr	   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   Ú
stop_eventzthreading.EventrZ   r   r[   r	   r   r   ÚNoner   )r   s   "r   r   rO   –   s=   € ÷ Xñ XØ)ðXØ8;ðXØJMðXàðXð 
ñXr   c               ó   € R# )z¥Begin firing due jobs. Built-in BLOCKS until stop_event is set (run in a daemon thread);
an external provider may return immediately but must still honor stop_event.Nr   )rR   r]   rZ   r[   r	   s   &&$$$r   ÚstartÚCronScheduler.start•   rU   r   c               ó   € V ^8„  d   QhRR/# ©r   r   r^   r   )r   s   "r   r   rO   �   s   € ÷ ñ �dñ r   c                ó   € R# )z:Optional eager teardown; stop_event is the primary signal.Nr   rQ   s   &r   ÚstopÚCronScheduler.stop�   ó   € ár   c               ó   € V ^8„  d   QhRR/# rc   r   )r   s   "r   r   rO   £   s   € ÷ ñ  ñ r   c                ó   € R# )zQAfter a successful store mutation; external providers reconcile. Built-in: no-op.Nr   rQ   s   &r   Úon_jobs_changedÚCronScheduler.on_jobs_changed£   rg   r   c               ó    € V ^8„  d   QhRRRR/# )r   Újobzdict[str, Any]r   r^   r   )r   s   "r   r   rO   §   s   € ÷ ñ  ð °4ñ r   c                ó   € R# )zRegister the external trigger for a newly persisted job (must complete before callers
report it as scheduled). Built-in: no-op.Nr   )rR   rm   s   &&r   Úregister_jobÚCronScheduler.register_job§   s   € ñ 	r   c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   rO   ¬   s   € ÷ 0ñ 0 Sñ 0r   c                ó   € ^ RI Hp V! 4       # )z@Run profile-local attempt recovery for every provider lifecycle.)Úrecover_interrupted_executions)Úcron.executionsrs   )rR   rs   s   & r   Úrecover_interruptedÚ!CronScheduler.recover_interrupted¬   s   € åBá-Ó/Ð/r   c               ó   € V ^8„  d   QhRR/# r9   r   )r   s   "r   r   rO   ³   s   € ÷ 2ñ 2 Tñ 2r   c                ó   € \        V 4      # )zPWhether ``fire_due`` accepts ``force`` (signature-detected for older providers).)Úprovider_supports_force_firerQ   s   &r   Úsupports_force_fireÚ!CronScheduler.supports_force_fire²   s   € ô ,¨DÓ1Ð1r   ÚforceFÚmanualc               ó0   € V ^8„  d   QhRRRRRRRRRRR	R/# )
r   Újob_idrH   rZ   r   r[   r|   r:   r}   r   r   )r   s   "r   r   rO   ·   sF   € ÷ Lñ LØðLØ(+ðLØ:=ðLØMQðLàðLð 
ñLr   c               óZ   € V P                  WVR7      pVf   R# V P                  WbVR7      # )a…  Run one job NOW (inbound fire webhook entry). Store CAS claim (multi-machine
at-most-once) then shared ``run_one_job``. True if THIS caller claimed and processed the
attempt (even if the job failed); False if the claim was lost or the job is gone.
``manual`` marks an off-tick run-now (dashboard trigger): the claim must not stamp
``next_run_at`` as the occurrence, or that slot is skipped when it arrives. Webhook and
misfire fires arriving at/after the due instant run that slot and keep the stamp; a fire
arriving BEFORE the stored instant is off-tick like ``manual`` and stays occurrence-free
(it cannot be the tick that owns a future slot).)r|   r}   F)rZ   r[   )Ú
claim_fireÚfire_claimed)rR   r   rZ   r[   r|   r}   Úclaimed_jobs   &&$$$$ r   Úfire_dueÚCronScheduler.fire_due·   s5   € ð —o‘o fÀ&�oÓIˆØÒÙØ× Ñ  ÀdÐ ÓKÐKr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   rH   r|   r:   r}   r   zdict | Noner   )r   s   "r   r   rO   È   s)   € ÷ ñ  ð °ð Àdð ÐWbñ r   c          	     óð  € ^ RI HpHpHp ^ RIHp V! WP                  R7      pRR/p	V'       d   RV	R&   V'       d   RV	R&    V! V3/ V	B p
\        V
\        4      '       d    V! VR,          V
P                  R	4      4       \        T
\        4      '       g   T! TR,          R
RR7       R# TR,          T
R&   T
#   \         d2   pT! TR,          R
R\        T4      P                   RT 2R7       h Rp?ii ; i)z¨Durably claim one fire + create its audit attempt. Transports call this synchronously
before acknowledging, then pass the exact snapshot to ``fire_claimed`` off-thread.)Úcreate_executionÚfinish_executionÚset_execution_occurrence)Úclaim_job_for_fire)ÚsourceÚ
return_jobTr|   r}   ÚidÚ_scheduled_instantFz#Fire claim failed before dispatch: ú: )ÚsuccessÚerrorNzFire claim was not acquiredÚexecution_id)rt   rˆ   r‰   rŠ   rG   r‹   rS   r-   ÚdictÚgetr   ÚtypeÚ__name__)rR   r   r|   r}   rˆ   r‰   rŠ   r‹   Ú	executionÚclaim_kwargsrƒ   r   s   &&$$        r   r�   ÚCronScheduler.claim_fireÈ   sõ   € ÷ 	aÑ`Ý0á$ V·I±IÔ>ˆ	Ø$ dÐ+ˆßØ$(ˆL˜Ñ!ßØ%)ˆL˜Ñ"ð		Ù,¨VÑD°|ÑDˆKÜ˜+¤t×,Ò,Ù(¨°4­¸+¿/¹/ÐJ^Ó:_Ô`ô ˜+¤t×,Ò,Ù˜Y t�_°eÐC`ÕaÙØ&/°¥oˆ�NÑ#ØÐøô ô 	ÙØ˜$•¨Ø;¼DÀ»I×<NÑ<NÐ;OÈrÐRUÐQVÐWõð ûð	ús   Á>B9 Â9C5Ã,C0Ã0C5Úcancel_eventc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   rƒ   r”   rZ   r   r[   r›   r   r:   r   )r   s   "r   r   rO   ä   s6   € ÷ 	ñ 	Øð	Ø.1ð	Ø@Cð	àð	ð 
ñ	r   c               ó&   € ^ RI Hp V! WW4R7       R# )z€Run an exact ``claim_fire`` snapshot; ``cancel_event`` lets the transport stop it
cooperatively (e.g. dashboard lifespan drain).)Úrun_one_job)rZ   r[   r›   T)r   rž   )rR   rƒ   rZ   r[   r›   rž   s   &&$$$ r   r‚   ÚCronScheduler.fire_claimedä   s   € õ 	/á�K¸ÕYÙr   c               ó   € V ^8„  d   QhRR/# rc   r   )r   s   "r   r   rO   ï   s   € ÷ ñ ˜4ñ r   c                ó   € R# )zQConverge the external registry toward jobs.json (desired state). Built-in: no-op.Nr   rQ   s   &r   Ú	reconcileÚCronScheduler.reconcileï   rg   r   r   )r—   Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Úpropertyr   rS   rX   r`   re   rj   ro   ru   rz   r„   r�   r‚   r¢   Ú__static_attributes__r   r   r   rL   rL   ˆ   sæ   † ñSð Øô;ó ó ð;õð ðXØ>BðXØPTðXàöXó ðXõõõõ
0ð ô2ó ð2ðLØ.2ðLØ@DðLØTYðLà÷Lð"°uð ÈU÷ ð8	Ø48ð	ØFJð	à ÷	÷ñ r   rL   c               ó    € V ^8„  d   QhRRRR/# ©r   Úproviderr   r   r:   r   )r   s   "r   r   r   ô   s   € ÷ 8ñ 8¨3ð 8°4ñ 8r   c                ó   € \        V R4      # )zZReturn whether a provider can safely receive ``fire_due(force=...)`` (signature-detected).r|   )Úprovider_fire_due_accepts)r¬   s   &r   ry   ry   ô   s   € ä$ X¨wÓ7Ð7r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r¬   r   rS   rH   r   r:   r   )r   s   "r   r   r   ù   s!   € ÷ ñ ¨ð °3ð ¸4ñ r   c                ó  a€  \         P                  ! V P                  4      P                  P	                  4       p\        ;QJ d    T3R lT 4       F  '       g   K   R# 	  R# ! T3R lT 4       4      #   \
        \        3 d     R# i ; i)z\Whether ``provider.fire_due`` takes keyword ``name`` (third-party providers may predate it).Fc              3  ó0  <"  € T F‹  pVP                   \        P                  P                  J ;'       gY    VP                  S8H  ;'       dB    VP                   \        P                  P
                  \        P                  P                  39   x € K�  	  R # 5i©N)ÚkindÚinspectÚ	ParameterÚVAR_KEYWORDrS   ÚPOSITIONAL_OR_KEYWORDÚKEYWORD_ONLY)Ú.0ÚprS   s   & €r   Ú	<genexpr>Ú,provider_fire_due_accepts.<locals>.<genexpr>ÿ   s€   øé € ð ñ ˆAð 	
�‰”'×#Ñ#×/Ñ/Ð/÷ 	
ð 	
à�F‰F�d‰N÷ dð dØ—‘œ7×,Ñ,×BÑBÄG×DUÑDU×DbÑDbÐcÑcô	
ó
 ùs   ƒ1BµBÁA
BT)r´   Ú	signaturer„   Ú
parametersÚvaluesÚ	TypeErrorÚ
ValueErrorÚany)r¬   rS   r¾   s   &f r   r®   r®   ù   s‡   ø€ ðÜ×&Ò& x×'8Ñ'8Ó9×DÑD×KÑKÓMˆ
÷ ‹3ô ñ ó�3Œ3ð Š3ð ˆ3ô ñ óó ð øô ”zÐ"ô Úðús   ƒ8A5 Á5B
Â	B
c               ó    € V ^8„  d   QhRRRR/# r«   r   )r   s   "r   r   r   	  s   € ÷ %ñ %¨3ð %°4ñ %r   c                ó‚   a€ \        V 4      oR V3R llpV! R4      '       g   V! R4      '       d   R# V! R4      '       * # )uâ   Whether a provider implements the two-phase fire contract. A legacy provider overriding only
``fire_due`` must keep being driven through it â€” routing around the override would drop its
custom claim/re-arm/telemetry behavior.c               ó    € V ^8„  d   QhRRRR/# )r   rS   rH   r   r:   r   )r   s   "r   r   Ú2provider_supports_split_fire.<locals>.__annotate__  s   € ÷ Mñ M˜ð M ñ Mr   c                óZ   <€ \        SV R 4      pVR J;'       d    V\        \        V 4      J# r²   )ÚgetattrrL   )rS   ÚimplÚclss   & €r   Ú	overridesÚ/provider_supports_split_fire.<locals>.overrides  s0   ø€ Ü�s˜D $Ó'ˆØ˜4Ð×LÐL D´¼ÀtÓ0LÐ$LÐLr   r�   r‚   Tr„   )r–   )r¬   rË   rÊ   s   & @r   Úprovider_supports_split_firerÍ   	  sB   ø€ ô ˆx‹.€C÷Mð Mñ �×Ò¡)¨N×";Ò";ÙÙ˜Ó$Ô$Ð$r   c               ó   € V ^8„  d   QhRR/# )r   r   r
   r   )r   s   "r   r   r     s   € ÷ 
4ñ 
4 ñ 
4r   c            	     ó”   €  ^ RI Hp Hp V! 4       p\        V ! VRR\        R7      4      #   \
         d    \        \        4      u # i ; i)zU``cron.misfire_grace_minutes`` from config; non-positive disables the catch-up sweep.©Úcfg_getÚload_configÚcronÚmisfire_grace_minutes©Údefault)Úhermes_cli.configrÑ   rÒ   r
   ÚDEFAULT_MISFIRE_GRACE_MINUTESr5   )rÑ   rÒ   Úconfigs      r   Ú_misfire_grace_minutesrÚ     sK   € ð4ß:á“ˆÜÙ�F˜FÐ$;ÔEbÔcó
ð 	
øô ô 4ÜÔ2Ó3Ò3ð4ús   ‚'* ªAÁArZ   r[   Únowc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r¬   rL   rZ   r   r[   rÛ   r   r   r   )r   s   "r   r   r   %  s;   € ÷ [ñ [Øð[Ø*-ð[Ø<?ð[ØMPð[àñ[r   c          
     ó�  € \         P                  ! \        4      ;_uu_ 4        ^ RIHp V! R\
        4      '       d    RRR4       ^ #  RRR4       ^ RIHp \        V \        4      '       d   ^ # \        4       pV^ 8:  d   ^ # ^ RI
HpHpHp	Hp
HpHp Vf   V
! 4       p^ pV! 4        EF©  pV! V4      '       g   K  VP#                  R4      pV'       g   K/   V	! VP%                  V4      4      pT! TT4      pTT^<,          8  d   K`  \+        TP#                  R4      ;'       g    R4      pTP#                  R	4      ;'       g    / p\+        TP#                  R
4      ;'       g    R4      R8X  dE   TT8”  d>   \
        P-                  RTTP#                  R4      ;'       g    RTT^<,          T4       EK  \
        P-                  RTTP#                  R4      ;'       g    RTT^<,          4        T P/                  T4      pTf   EK^  \0        P2                  ! T P4                  T3RTRT/RRTR,           2R7      P7                  4        T^,          pEK¬  	  V#   + '       g   i     EL; i  \&        \(        3 d     EKÙ  i ; i  \8         d8   p\
        P-                  RT\;        T4      P<                  T4        Rp?EK  Rp?ii ; i)aÂ  Misfire backstop (gateway housekeeping loop): fire jobs whose external HTTP fire never
arrived, else ``next_run_at`` stays parked in the past forever. No-op for the built-in (its tick
loop self-heals). Routes through the provider's own two-phase path so re-arm logic runs and a
concurrent late external retry is de-duplicated by the store CAS; waits out
``cron.misfire_grace_minutes`` so the external retry gets first right. Returns jobs dispatched.
)Úcheck_pausedzcron-misfireN)Údatetime)ÚONESHOT_GRACE_SECONDSÚ_elapsed_secondsÚ_ensure_awareÚ_hermes_nowÚis_job_runnableÚ	load_jobsÚnext_run_atrŽ   Ú Úscheduler³   Úonceu{   Misfire catch-up: one-shot job %s (%s) was due %s (%.0f min overdue) â€” outside the %ss one-shot grace window, not firing.rS   Úunnamedul   Misfire catch-up: job %s (%s) was due %s (%.0f min overdue) and no external fire arrived â€” firing locally.rZ   r[   Tzcron-misfire-:Né   N)rA   r&   r'   ÚdaemonrS   z*Misfire catch-up failed for job %s: %s: %s)Ú
contextlibÚsuppressÚImportErrorÚagent.estoprÞ   r"   rß   r-   ÚInProcessCronSchedulerrÚ   rG   rà   rá   râ   rã   rä   rå   r•   ÚfromisoformatrÁ   rÀ   rH   r#   r�   Ú	threadingÚThreadr‚   r`   r5   r–   r—   )r¬   rZ   r[   rÛ   Ú_estop_check_pausedrß   Úgrace_minutesrà   rá   râ   rã   rä   rå   Úfiredrm   ræ   Údue_dtÚoverdue_secondsr   rè   Úclaimedr   s   &$$$                  r   Úfire_overdue_jobsrû   %  su  € ô 
×	Ò	œ[×	)Õ	)ÝCÙ˜~¬v×6Ò6Ø÷ 
*Ñ	)à6÷ 
*õ
 "ä�(Ô2×3Ò3Ùä*Ó,€MØ˜ÔÙ÷÷ ð
 ‚{Ù‹mˆà€EÙ�{ˆÙ˜s×#Ò#ÙØ—g‘g˜mÓ,ˆßÙð	Ù" 8×#9Ñ#9¸+Ó#FÓGˆFñ +¨3°Ó7ˆØ˜]¨RÕ/Ô/ÙÜ�S—W‘W˜T“]×(Ð( bÓ)ˆð
 —7‘7˜:Ó&×,Ð,¨"ˆÜˆx�|‰|˜FÓ#×)Ð) rÓ*¨fÔ4¸ÐK`Ô9`Ü�N‰Nð&ð Ø—‘˜“×,Ð, 9ØØ "Õ$Ø%ô	ò Ü�‰ð;àØ�G‰G�F‹O×(Ð(˜yØØ˜bÕ ô	
ð	à×)Ñ)¨&Ó1ˆGØŠÚÜ×ÒØ×,Ñ,°G°:Ø" H¨f°dÐ;ÀDØ$ V¨C¥[ MÐ2ô÷ ‰eŒgØ�Q�J‹Eñc ðn €L÷] 
*×	)Ð	)ûô> œIÐ&ô 	Ûð	ûôT ô 	Ü�N‰NØ<Øœ˜S›	×*Ñ*¨C÷ó ûð	ús<   £IÃI*Ç,JÈAJÉI'	É*J É?J ÊKÊ+K Ë Kc               ó   € V ^8„  d   QhRR/# )r   r   rL   r   )r   s   "r   r   r   ƒ  s   € ÷ (ñ ( ñ (r   c                 óD  € Rp  ^ RI HpHp V! V! 4       RRRR7      ;'       g    RP                  4       p V '       d   V R9   d   \        4       #  ^ RIHp V! V 4      pVf!   \        P                  RV 4       \        4       # VP                  4       '       g!   \        P                  R	V 4       \        4       # \        P                  R
VP                  4       V#   \         d     L±i ; i  \         d+   p\        P                  RY4       \        4       u Rp?# Rp?ii ; i)u˜   Resolve ``cron.provider``; missing/failing/unavailable providers fall back to the built-in
with a warning â€” cron must never be left without a trigger.rç   rÐ   rÓ   r¬   rÕ   )Úload_cron_schedulerNz3cron.provider '%s' not found; using built-in tickerz7cron.provider '%s' not available; using built-in tickerz!Using cron scheduler provider: %sz=Failed to load cron.provider '%s' (%s); using built-in ticker)Úbuiltinz
in-processÚ	inprocess)r×   rÑ   rÒ   Ústripr5   rñ   Úplugins.cron_providersrþ   r"   r#   rX   ÚinforS   )rS   rÑ   rÒ   rþ   r¬   r(   s         r   Úresolve_cron_schedulerr  ƒ  sù   € ð €Dðß:Ù™› v¨zÀ2ÔF×LÐLÈ"×SÑSÓUˆ÷ �4ÐAÔAÜ%Ó'Ð'ð(Ý>Ù& tÓ,ˆØÒÜ�N‰NÐPÐRVÔWÜ)Ó+Ð+Ø×$Ñ$×&Ò&Ü�N‰NÐTÐVZÔ[Ü)Ó+Ð+Ü�‰Ð7¸¿¹ÔGØˆøô! ô Ùðûô" ô (Ü�‰ÐVÐX\Ô`Ü%Ó'Õ'ûð(úsF   „C ¤C Á1C* ÂC* ÂC* Â7!C* ÃC'Ã&C'Ã*DÃ5DÄDÄDc               ó$   € V ^8„  d   QhRRRRRR/# )r   r¬   rL   Úmultiplex_profilesr:   r   r   )r   s   "r   r   r      s$   € ÷ $ñ $Øð$Ø48ð$àñ$r   c               ó–   € V'       d   \        V \        4      '       d   V # \        P                  RV P                  4       \        4       # )zµExternal providers own one unscoped remote registry and cannot reconcile several profile
stores: fail closed to the built-in multiplex ticker until the API carries profile identity.zMcron.provider '%s' does not support multiplex_profiles; using built-in ticker)r-   rñ   r"   r#   rS   )r¬   r  s   &$r   Úscheduler_for_profile_moder     s:   € ÷
 ¤¨HÔ6L×!MÒ!MØˆÜ
‡N�NØWØ�‰ôô "Ó#Ð#r   c                  ó€   € ] tR tRtRt]R R l4       tRRRRR^<R	RR
RRRRRRR/R ltRRRRR^<R	RRRRRRR/R ltRt	R# )rñ   i®  z²Default in-process 60s ticker; ``start()`` blocks until ``stop_event``. ``can_dispatch`` is
an optional drain gate; skipped ticks leave due jobs intact for the next allowed tick.c               ó   € V ^8„  d   QhRR/# rN   r   )r   s   "r   r   Ú#InProcessCronScheduler.__annotate__³  s   € ÷ ñ �cñ r   c                	ó   € R # )rÿ   r   rQ   s   &r   rS   ÚInProcessCronScheduler.name²  s   € ár   rZ   Nr[   r	   Úcan_dispatchr1   Úprofile_adaptersÚdefault_profileÚprofile_gatec               	óø  € ^ RI Hp
 ^ RI Hp ^ RIHpHpHp ^ RIHp ^ RI	H
p \        P                  RV4       Ve2   \        V4      '       g	   V'       d   V P                  WW#WEVW‰R7	       R# V! V! 4       .4        V P                  4       pV'       d   \        P!                  R	V4       V! 4        ^ p\,        P.                  ! 4       pVP1                  4       '       g»   Rp Ve$   V! 4       '       g   \        P3                  R4       MV! RW#RVR7       Rp\'        VRVR7       V'       d   \'        VR4       ^ p\9        VV4      pVV,          p\,        P.                  ! 4       pVV8  d
   VV,           pVP;                  \=        RVV,
          4      4       KÐ  R#   \"         dI   p\        P%                  R
TRR7       \'        TR\)        T4      P*                   RT 24        Rp?EL7Rp?ii ; i  \"         d~   p\5        TT
4      '       d   \        P                  RT4       M\        P%                  RTRR7       \'        TR\)        T4      P*                   RT 24       \7        TT4      p Rp?EL]Rp?ii ; i)é    )ÚCronTickYielded©Útick©Úclear_ticker_errorÚrecord_ticker_errorÚrecord_ticker_heartbeat©Úregister_ticked_homes)Úget_process_hermes_homez0In-process cron scheduler started (interval=%ds)N)r1   rZ   r[   r	   r  r  r  r  z=Marked %d interrupted cron execution(s) unknown after restartzCron startup recovery error: %sTr    zstartup errorr�   Fú7Cron dispatch paused while gateway drains existing work©ÚverboserZ   r[   Úsyncr  zCron tick yielded: %súCron tick error: %sú
tick errorÚ	heartbeat©r‘   úerror clearç        )r   r  r  rG   r  r  r  Úcron.scheduler_ownershipr  r?   r  r"   r  r4   Ú_start_multiplexru   r#   r   r’   r)   r–   r—   ÚtimeÚ	monotonicÚis_setÚdebugr-   r   r   ÚwaitÚmax)rR   r]   rZ   r[   r	   r  r1   r  r  r  r  Ú	cron_tickr  r  r  r  r  Ú	recoveredr(   r   Ú	next_tickÚokÚwait_forrÛ   s   &&$$$$$$$$              r   r`   ÚInProcessCronScheduler.start¶  s=  € õ 	3Ý4ß^Ñ^ÝBÝ<ä�‰ÐFÈÔQð Ò$¬(°=×*AÒ*AÇ]Ø×!Ñ!ØÀ(Ø!ÐO_Ø /ð "ô ñ
 ñ 	Ñ6Ó8Ð9Ô:ð
	Ø×0Ñ0Ó2ˆIßÜ—‘ØSÐU^ôñ
 $Ô%ð  !ÐÜ—N’NÓ$ˆ	Ø×#Ñ#×%Ò%ØˆBðSØÒ+±L·N²NÜ—L‘LÐ!ZÕ[áØ %°È%Ø%1õð �ô0 !Ð!8¸+ÈrÕRßÜ$Ð%7¸ÔGØ'(Ð$Ü,¨XÐ7KÓLˆHØ˜Õ!ˆIÜ—.’.Ó"ˆCØ˜3Œð   (�N�	Ø�O‰OœC  Y°¥_Ó5Ö6ñ[ &øô ô 	Ü�L‰LÐ:¸AÈˆLÔMÜ Ø# _¼¸a»×9IÑ9IÐ8JÈ"ÈQÈCÐ6P÷ò ûð	ûô& !ô Sô ˜a ×1Ò1ä—K‘KÐ 7¸Õ;ä—L‘LÐ!6¸ÀD�LÔIä$Ø'¨¼$¸q»'×:JÑ:JÐ9KÈ2ÈaÈSÐ7Qôô (:¸!Ð=QÓ'RÖ$ûð#Sús=   Á=F ÂF Ã"G1 Ã3$G1 ÆG.Æ&=G)Ç)G.Ç1I9Ç<A2I4É4I9c               óÒ
  aaaa'a(€ ^ RI Hp
 ^ RI HpHp ^ RIHo'Ho( ^ RIHpH	pH
p ^ RIHp \        V4      pT! V Uu. uF  p\        V4      ^,          NK  	  up4       \        P!                  R\#        V4      V Uu. uF$  p\%        V\&        4      '       d
   V^ ,          MTNK&  	  up\)        V4      '       d   RMR4       V'V(VVV3R	 lpV Fd  p\        V4      w  pp \+        V4      ;_uu_ 4        V P-                  4       pV'       d   \        P/                  R
VV4       V! 4        RRR4       Kf  	  ^ p\4        P6                  ! 4       pVP9                  4       '       Eg   RpRp/ pRp. p \        V4       Uu. uF  p\        V4      NK  	  p pV	e*   V  U!Uu. uF  w  p!pV	! V!V4      '       g   K  V!V3NK  	  p p!pT pT! V U"Uu. uF  w  p"pVNK
  	  upp"4        Ve$   V! 4       '       g   \        PA                  R4       MSV F6  w  p#p \+        V4      ;_uu_ 4        V
! RV! V#4      VRVR7       RRR4       K8  	  V'       * pVe   \?        VV4      pV F¢  w  pp\+        V4      ;_uu_ 4        VRJ ;'       d    \C        V4      V9  p$\E        VRV$R7       V$'       d   \E        VR4       MC\C        V4      V9   d   \E        VRV\C        V4      ,          4       MV'       d   \E        VRV4       RRR4       K¤  	  V'       d   ^ p\G        VV4      p%VV%,          p\4        P6                  ! 4       p&VV&8  d
   V&V%,           pVPI                  \K        RVV&,
          4      4       EK  R# u upi u upi   + '       g   i     EKº  ; i  \0         d&   p\        P3                  RTTRR7        Rp?EKè  Rp?ii ; iu upi u upp!i u upp"i   \0         dJ   p\        P3                  RTRR7       \;        T4      P<                   RT 2p\?        TT4      p Rp?EL@Rp?ii ; i  + '       g   i     EK0  ; i  T dJ   p\        P!                  RTT4       \;        T4      P<                   RT 2T\C        T4      &    Rp?EK~  Rp?i\0         dg   p\        P3                  RTTRR7       \;        T4      P<                   RT 2T\C        T4      &   Te   T! T4      '       d
   Tp Rp?EKæ   Rp?EKí  Rp?ii ; i  \0         dJ   p\        P3                  RTRR7       \;        T4      P<                   RT 2p\?        TT4      p Rp?ELóRp?ii ; i  + '       g   i     EK  ; i)z¾Tick every profile's store, each scoped via ``_profile_cron_scope``. ``profile_gate(name,
home)``, when given, is consulted every cycle; a rejected profile is neither ticked nor
heartbeated.r  )r  r   )ÚSharedRouteAdaptersÚ(_primary_profile_routes_for_current_homer  r  z8Multiplex cron scheduler started for %d profile(s): %s%sz (re-enumerated every cycle)rç   c                ó¨   <€ V e   V S8X  d   S# S;'       g    / P                  V 4      ;'       g    / pV'       g   S'       d   S! SS! 4       4      # V# r²   )r•   )Úprofile_nameÚtick_adaptersr7  r8  rZ   r  r  s   & €€€€€r   Útick_adapters_forÚBInProcessCronScheduler._start_multiplex.<locals>.tick_adapters_for.  sS   ø€ ð Ò# |°Ô'FØ�Ø-×3Ð3°×8Ñ8¸ÓF×LÐLÈ"ˆMß §XÙ*¨8Ñ5]Ó5_Ó`Ð`Ø Ð r   z9Marked %d interrupted cron execution(s) for profile at %sNz1Cron startup recovery error for profile at %s: %sTr    Fz"Cron profile enumeration error: %sr�   r  r  z'Cron tick yielded for profile at %s: %sz%Cron tick error for profile at %s: %sr"  r$  r%  r&  r#  r'  )&r   r  r  r   Úcron.scheduler_preflightr7  r8  rG   r  r  r  r(  r  r7   r/   r"   r  Úlenr-   r+   r4   rJ   ru   r#   r   r’   r*  r+  r,  r–   r—   r   r-  rH   r)   r   r.  r/  ))rR   r]   r1   rZ   r[   r	   r  r  r  r  r0  r  r   r  r  r  r  Úinitial_homesr.   rº   r<  Ú_r@   r1  r(   r   r2  r3  Ú_tick_errorÚ_profile_errorsÚ
_cycle_excÚcycle_homesÚ
enumeratedrS   Ú_nameÚ_pnameÚ_home_okr4  rÛ   r7  r8  s)   &&$d$$$dd$                             @@r   r)  Ú'InProcessCronScheduler._start_multiplex  sí  ü€ õ 	5ßE÷	
÷ 	_Ñ^ÝBä/°Ó>ˆÙÁ]ÓSÁ]¸Eœ~¨eÓ4°Q×7Ð7Á]ÑSÔTÜ�‰ØFÜ�ÓÙ:GÓH¹-°Q”Z ¤5×)Ò)ˆQˆqŽT¨qÒ0¹-ÑHÜ.6°}×.EÒ.EÑ*È2ô		
÷		!ñ 		!ó #ˆEÜ$ UÓ+‰GˆAˆtðÜ(¨×.Õ.Ø $× 8Ñ 8Ó :�Iß ÜŸ™ØWØ% tôñ ,Ô-÷ /Ñ.ñ #ð   !ÐÜ—N’NÓ$ˆ	Ø×#Ñ#×%Ó%ØˆBØˆKØ.0ˆOð 04ˆJð
 !#ˆKðSÜ9PÐQ^Ô9_Ó`Ñ9_°Aœn¨QÖ/Ñ9_�
Ð`ØÒ+ÙAKÔ!hÁ±:°4¸É|Ð\`Ðbf×Og¤, 4¨£,Á�JÑ!hØ(�ñ &¹{Ô&K¹{±°°t£t¹{Ò&KÔLð
SØÒ+±L·N²NÜ—L‘LÐ!ZÕ[ã(3™˜ ð/Ü!4°T×!:Õ!:Ù )Ø,1Ñ<MÈfÓ<UÐ\`Ø).¸\õ!"÷ ";Ñ!:ñ )4ð& -Ô,�BØ!Ò-Ü/AÀ*ÐNbÓ/cÐ,ó '‘��4Ü(¨×.Õ.Ø*¨dÐ2×WÐW´s¸4³yÈÑ7W�HÜ(Ø/°Àhõ÷  Ü,Ð-?ÀÕOÜ˜T› oÔ5Ü,Ø/Ø(Ø+¬C°«IÕ6õ÷
 %Ü,Ø/°¸{ô÷ /Ñ.ñ '÷$ Ø'(Ð$Ü,¨XÐ7KÓLˆHØ˜Õ!ˆIÜ—.’.Ó"ˆCØ˜3Œð   (�N�	Ø�O‰OœC  Y°¥_Ó5×6ñi &ùòQ Tùò I÷* /×.Ñ.ûô !ô Ü—‘ØGÈÈqÐ[_ð ÷ ó ûðüò( aùã!hùó
 'LøÜ ô SÜ—‘ÐAÀ1Èt�ÔTÜ!% a£×!1Ñ!1Ð 2°"°Q°CÐ8�Ü'9¸!Ð=QÓ'RÖ$ûðSú÷ ";×!:Ñ!:ûð
  /ô Tä"ŸK™KÐ(QÐSWÐYZÔ[Ü<@À»G×<LÑ<LÐ;MÈRÐPQÈsÐ9S˜O¬C°«I×6Ð6ûÜ,ô /ä"ŸL™LØ GÈÈqÐ[_ð )ô ô =AÀ»G×<LÑ<LÐ;MÈRÐPQÈsÐ9S˜O¬C°«IÑ6Ø)Ò1Ñ5FÀq×5IÒ5IØ-.§
ö 6Jûð/ûô !ô SÜ—‘Ð2°AÀ�ÔEÜ!% a£×!1Ñ!1Ð 2°"°Q°CÐ8�ä'9¸!Ð=QÓ'RÖ$ûð	Sú÷ /×.Ñ.ús-  ½M,Á=*M1Ã NÃ37M6Ä*NÅ/O Å<N>ÆO ÆOÆ4OÆ<O ÇO	
ÇO ÇS= Ç0S= ÈS= ÈP;È"P&È6P;È>S= É4A3UË(UÍ6NÎNÎNÎN;ÎN6Î6N;Î>O ÏP#Ï>PÐP#Ð&P8Ð1P;Ð5S= Ð8P;Ð;S:Ñ=RÑ?S= ÒS:ÒS:ÒAS5Ó%S5Ó'S= Ó5S:Ó:S= Ó=UÔ>UÕUÕU&r   )
r—   r¤   r¥   r¦   r§   r¨   rS   r`   r)  r©   r   r   r   rñ   rñ   ®  s¶   † ñ^ð ôó ðð^7Ø&*ð^7Ø15ð^7Ø@Bð^7ØQUð^7àð^7à-1ð^7àCGð^7àVZô^7ð@L7Ø59ðL7Ø@DðL7ØOQðL7àðL7à,0ðL7àBFðL7àUY÷L7ð L7r   rñ   i„  r²   )%r§   Ú
__future__r   rí   r´   Úloggingró   r*  Úabcr   r   Úpathlibr   Útypingr   Ú	getLoggerr—   r"   r   rØ   r   r   r)   r/   r7   rB   ÚcontextmanagerrJ   rL   ry   r®   rÍ   rÚ   rû   r  r  rñ   r   r   r   Ú<module>rR     sß   ðñõ
 #ã Û Û Û Û ß #Ý Ý à	×	Ò	˜8Ó	$€ð &Ð Ø "Ð õYõò Rõ@õY÷*Yð. ×Ññ/ó ð/ô"i�Cô iõX8õ
õ %õ
4ð[Ø04ð[ØBFð[ØSW÷[õ|(õ:$ôt7˜]ö t7r   