+
    lHàj4I ã                   ó0  a€ R‰ t‰0 t R t^ RIt^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ]P&                  ! 4       R8H  t]P&                  ! 4       R8H  t^ RIHtHtHtHt ^ RIHt ^ RIHtHt ^ R	I H!t!H"t"H#t#H$t$H%t%H&t& ^ R
I'H(t( ^ RI)H*t*H+t+H,t,H-t- ^ RI.H/t/ ^ RI0H1t1H2t2H3t3H4t4 ^ RI5H6t6 ^ RI7H8t8H9t9 ^ RI:H;t; ^ RI<H=t= ]P|                  ! ]?4      t@](! 4       R,          tA]AtBR R ltCRtDRtERtF^@tG^tH^tI^tJ^<tK^tLRŠtMRtN^tO^
tP^tQRsR] ^ k ]P¦                  ! 4       tTRsURtVRsWR‹tXRŒtYR�tZR R lt[R R lt\R  R! lt]R" R# lt^RŽR$ R% llt_R& R' lt`R( R) ltaR* R+ ltbR, R- ltcR.sd ! R/ R0]e4      tfR1 R2 ltgR3thR4ti ! R5 R6]%4      tjR7 R8 ltkR9R./R: R; lltlR< R= ltmR> R? ltnR@ RA ltoRB RC ltpRD RE ltq] ! RF RG4      4       trR�ts. R�ORI ]s 4       ORJNRKNRLNRMNRNNRONRPNRQN5tt]rPê                  Pí                  4        U u/ uF@  p V Pî                  ]t9   g   K  V Pî                  V Pî                  RN8X  d   . MV Pð                  bKB  	  up tyRRtz ! RS RT]6]/]14      t{]{! 4       t|^ RUI}H~t~Ht RVRWRXRYRZR[R\R]R^R[R_R`. R‘O/RhR[R_RXRi/RjR[R_RXRk/RlR[RmRXRnRo^/RpR[RmRXRq/RrR[RmRXRsRo^//RtR^.//t€RHRu/Rv Rw llt�Rx Ry lt‚Rz R{ ltƒRaR| R3RbR} R3RcR~ R3RdR R3ReR€ R.3RfR� R.3RgR‚ R.3/t„Rƒ R„ lt…^t†R… t‡]~EP                  ! RWR†]€]‡R‡Rˆ7       R# u up i )’aK  Process Registry -- in-memory registry for background processes spawned via
terminal(background=true): rolling 200KB output buffer, poll/log/wait/kill, JSON
checkpoint for crash recovery, session-scoped tracking for gateway reset protection.
Nothing runs on the host unless TERMINAL_ENV=local; other backends run in their sandbox.
N)Úsuppress©ÚPathÚWindowsÚLinux)Ú_find_shellÚ_resolve_safe_cwdÚ_sanitize_subprocess_envÚ_terminal_env)Úwindows_hide_flags)Ú	dataclassÚfield)ÚAnyÚDictÚListÚLiteralÚ
NamedTupleÚOptional)Úget_hermes_home)Úformat_process_notificationÚheartbeat_output_tailÚis_child_process_notificationÚshould_surface_notification)ÚProcessCheckpointMixin)ÚProcessOutputLogMixinÚopen_output_logÚrecord_exit_commandÚworker_output_log)ÚProcessTerminationMixin)Úload_completed_resultsÚsave_completed_result)Úlog_delta_command)Ú_is_wsl_launcher_commandúprocesses.jsonc                ó$   € V ^8„  d   QhR\         /# ©é   Úreturnr   )Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/tools/process_registry.pyÚ__annotate__r*   3   s   € ÷ vñ vœ$ñ vó    c                 óN   € \         \        8w  d   \         # \        4       R,          # )u+  Active profile's checkpoint file at call time: the patched ``CHECKPOINT_PATH`` when a test
changed it, else live profile-scoped HERMES_HOME â€” the multiplexed gateway serves every
profile from one process, so the import-time constant would pin every profile's process
checkpoint to the launch home.r#   )ÚCHECKPOINT_PATHÚ_CHECKPOINT_PATH_AT_IMPORTr   © r+   r)   Ú_checkpoint_pathr0   3   s!   € ô
 .Ô1KÔKŒ?ÐuÔQ`ÓQbÐeuÕQuÐur+   i@ éÐ  i  ç      ð?ç        g      N@Tc                ó$   € V ^8„  d   QhR\         /# r%   ©Úint)r(   s   "r)   r*   r*   }   s   € ÷ 3Mñ 3M¤#ñ 3Mr+   c                 ó¢  € Rp \         P                  ! RR4      P                  4       pV'       dK    \        V4      R,          R,          pV\
        8¼  d   Tp M"\        P                  RV\
        R,          4       . p \        R4      P                  RR7      P                  4        F·  pVP                  R	4      '       g   K  VP                  R
4      ^,          P                  R4      p\        R4      V,          R,          P                  RR7      P                  4       pVP                  4       '       d(   \        V4      pV\
        8¼  d   VP                  V4        M	    \        \         P"                  ! R4      4      \        \         P"                  ! R4      4      ,          p\%        \&        \)        \
        V^,          4      4      p	VP                  V	4       V'       d   \%        V4      M\,        p
V '       d   \%        W
4      # T
#   \         d    Rp ELÐi ; i  \         \        3 d     LÏi ; i  \         \        \*        3 d     Lqi ; i)aÙ  Finite per-worker cgroup limit that can never widen host risk.
``TERMINAL_LOCAL_MEMORY_MAX_MB`` is honored only when it *tightens* the safe
bound (min of the gateway's cgroup-v2 ``memory.max`` and half of physical RAM,
capped at 4 GiB), so an oversized override cannot exceed the enclosing slice.

The proposed local-memory-guard environment override is honored when it tightens the safe bound, so this
isolation composes with PR #57121 instead of inventing a second knob.
NÚTERMINAL_LOCAL_MEMORY_MAX_MBÚ i   zbIgnoring invalid TERMINAL_LOCAL_MEMORY_MAX_MB=%r; expected an integer representing at least %d MiBz/proc/self/cgroupúutf-8)Úencodingz0::z::Ú/z/sys/fs/cgroupz
memory.maxz	utf-8-sigÚSC_PHYS_PAGESÚSC_PAGE_SIZEéÿÿÿÿé   )ÚosÚgetenvÚstripr6   Ú
ValueErrorÚ_MIN_WORKER_MEMORY_MAX_BYTESÚloggerÚwarningr   Ú	read_textÚ
splitlinesÚ
startswithÚ	partitionÚlstripÚisdigitÚappendÚOSErrorÚsysconfÚminÚ_WORKER_MEMORY_MAX_CAP_BYTESÚmaxÚ	TypeErrorÚ _DEFAULT_WORKER_MEMORY_MAX_BYTES)Úoverride_boundÚoverrideÚparsedÚ
candidatesÚlineÚrelativeÚ	raw_limitÚcgroup_limitÚphysical_bytesÚphysical_boundÚ
safe_bounds              r)   Ú_worker_memory_max_bytesra   }   sõ  € ð %)€NÜ�yŠyÐ7¸Ó<×BÑBÓD€Hßð	Ü˜“] TÕ)¨DÕ0ˆFð Ô1Ô1Ø#‰Nä�N‰NðCàÔ6¸;ÕGôIð €JðÜÐ,Ó-×7Ñ7ÀÐ7ÓI×TÑTÖVˆDØ�‰˜u×%Ô%ØŸ>™>¨$Ó/°Õ2×9Ñ9¸#Ó>�äÐ)Ó*¨XÕ5¸ÕDß‘) [�)Ó1·%±%³'ð ð ×$Ñ$×&Ò&Ü#& y£>�LØ#Ô'CÔCØ"×)Ñ)¨,Ô7Ùò Wð
ÜœRŸZšZ¨Ó8Ó9¼CÜ�JŠJ�~Ó&ó=
õ 
ˆô Ü(ÜÔ,¨nÀÕ.AÓBó
ˆð 	×Ñ˜.Ô)÷ %/”�Z”Ô4T€Jß.<Œ3ˆ~Ó*ÐLÀ*ÐLøôK ô 	Ø‹Fð	ûô, ”ZÐ ô Ùðûô ”Z¤Ð+ô ÙðúsD   ±H
 Á=A H ÃBH ÅH Å#A9H5 È
HÈHÈH2È1H2È5IÉIc          	      ó^   € V ^8„  d   QhR\         R\         R\         R\        \         ,          /# )r&   ÚbinaryÚ	unit_nameÚargvr'   )ÚstrÚlist)r(   s   "r)   r*   r*   ³   s,   € ÷ ñ ¤ð ´ð ¼Cð ÄDÌÅIñ r+   c                ón   € \         '       d   R.M. pV RRR.VORNVNRNRNRNRNR	\        4        2NR
NVO# )a,  ``systemd-run --user --scope`` argv shared by the probe and real spawns.
``--collect`` self-cleans the scope after exit; ``--unit`` names it for systemctl.
No ``OOMPolicy=``: transient scopes reject it on systemd <253 (#102486).
``--expand-environment=no`` keeps the command byte-identical (#132385).z--expand-environment=noú--userz--scopez--quietz--unitz	--collectz
--propertyzMemoryAccounting=yesz
MemoryMax=z--)Ú_SYSTEMD_RUN_NO_EXPANDra   )rc   rd   re   Ú	no_expands   &&* r)   Ú_systemd_scope_argvrl   ³   sŒ   € ÷
 0FÓ/EÐ*Ñ+È2€Ià�˜) YðØ1:ðØ<DðØFOðØQ\ðàðà,ðð 	ðð #Ô#;Ó#=Ð">Ð?ðð 	ð	ð ð	ð r+   c                ó$   € V ^8„  d   QhR\         /# r%   r   )r(   s   "r)   r*   r*   Á   s   € ÷ ,ñ ,¤4ñ ,r+   c                 óD   € \        R\        P                  ! 4        24      # )zW``/run/user/<uid>``; a function so tests can point it at a temp dir with a real socket.z
/run/user/)r   rA   Úgetuidr/   r+   r)   Ú_default_user_runtime_dirrp   Á   s   € ä�*œRŸYšY›[˜MÐ*Ó+Ð+r+   c                ó0   € V ^8„  d   QhR\         R\        /# )r&   Úpathr'   )r   Úbool)r(   s   "r)   r*   r*   Æ   s   € ÷ ñ ¤4ð ¬Dñ r+   c                óH  €  V P                  4       pV P                  4       ;'       di    \        P                  ! VP                  4      ;'       dA    VP
                  \        P                  ! 4       8H  ;'       d    VP                  ^,          ^ 8H  #   \         d     R# i ; i)z<Accept only an absolute, owned, non-writable real directory.F)	ÚlstatÚis_absoluteÚstatÚS_ISDIRÚst_modeÚst_uidrA   ro   rO   )rr   Úmetadatas   & r)   Ú_secure_user_runtime_dirr|   Æ   sŽ   € ð	Ø—:‘:“<ˆà×ÑÓ÷ .ð .Ü—’˜X×-Ñ-Ó.÷.ð .à—‘¤2§9¢9£;Ñ.÷.ð .ð × Ñ  5Õ(¨AÑ-ð		
øô ô Úðús"   ‚&B ©'B Á)B Á;B ÂB!Â B!c                óŠ   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        \        \        3,          /# )r&   Úbase_envr'   )r   Údictrf   )r(   s   "r)   r*   r*   Ô   s0   € ÷ "ñ "¤8¬D´´c°­NÕ#;ð "ÄtÌCÔQTÈHÅ~ñ "r+   c                ó6  € \        V f   \        P                  MT 4      p\        '       g   V# VP	                  R4      pV'       d'   \        \        V4      4      '       d   \        V4      pM\        4       p\        V4      '       g   V# VR,          p VP                  4       p\        P                  ! TP                  4      '       d%   TP                  \        P                  ! 4       8w  d   T# \        T4      TR&   RT 2TR&   T#   \         d    Tu # i ; i)a  Build an environment that can reach this user's lingering systemd manager.

System-level gateway units run as an unprivileged ``User=`` but normally do
not inherit login-session variables.  When the conventional runtime
directory is owned by this uid and its bus exists, derive the two standard
variables.  Derived fresh on every call rather than adopted once at boot:
linger may be enabled after the gateway started (existing installs), so
the bus can appear later and the probe's failure TTL must be able to
recover (#104893).
The returned copy is passed explicitly to the probe and every scoped spawn;
``os.environ`` is left unchanged.
ÚXDG_RUNTIME_DIRÚbusz
unix:path=ÚDBUS_SESSION_BUS_ADDRESS)r   rA   ÚenvironÚ	_IS_LINUXÚgetr|   r   rp   ru   rO   rw   ÚS_ISSOCKry   rz   ro   rf   )r~   ÚenvÚ
configuredÚruntime_dirÚbus_pathÚbus_metadatas   &     r)   Úsystemd_user_bus_envr�   Ô   sî   € ô ˜XÒ-Œr�zŠz°8Ó
<€Cß‹9Øˆ
Ø—‘Ð*Ó+€JßÔ.¬t°JÓ/?×@Ò@Ü˜:Ó&‰ä/Ó1ˆÜ'¨×4Ò4ØˆJà˜UÕ"€HðØ—~‘~Ó'ˆô �=Š=˜×-Ñ-×.Ò.°,×2EÑ2EÌÏÊËÔ2TØˆ
ä  Ó-€CÐÑØ(2°8°*Ð&=€CÐ"Ñ#Ø€Jøô ô ØŠ
ðús   ÂD ÄDÄDc                ó:   € V ^8„  d   QhR\         \        ,          /# r%   )r   rs   )r(   s   "r)   r*   r*   ù   s   € ÷ 7ñ 7œx¬�~ñ 7r+   c                 ó„   € \         f   R# \        P                  ! 4       \        ,
          \        8¬  p V '       d   R# \         # )z6Cached probe verdict, or None when a (re)probe is due.N)Ú_SYSTEMD_SCOPE_AVAILABLEÚtimeÚ	monotonicÚ_SYSTEMD_SCOPE_PROBED_ATÚ _SYSTEMD_SCOPE_PROBE_TTL_SECONDS)Ústales    r)   Ú_systemd_scope_cachedr–   ù   s1   € äÒ'ÙÜ�NŠNÓÔ7Õ7Ô;[Ñ[€Eßˆ4Ð6Ô6Ð6r+   c                ó$   € V ^8„  d   QhR\         /# r%   ©rs   )r(   s   "r)   r*   r*     s   € ÷ 2ñ 2¬4ñ 2r+   c                 ó  € \        4       p V e   V # \        ;_uu_ 4        \        4       p V e   V uuRRR4       # Rp\        '       EdV    ^ RIpVP	                  R4      pV'       Ed7   R\
        P                  ! 4        R\        P                  ! 4       P                  R,           2p\        ^4       F~  p\        P                  ! \        W4RRR	4      \        P                  R
^\        4       RR7      pVP                   '       d(   \"        '       d   RVP$                  ;'       g    R9   g    MRsK€  	  XP                   ^ 8H  pV'       gT   \&        P)                  RVP                   VP$                  ;'       g    RP+                  RR4      P-                  4       4       Vs\2        P4                  ! 4       sVuuRRR4       #   \.         d!   p\&        P)                  RT4        Rp?LIRp?ii ; i  + '       g   i     R# ; i)a¤  True if ``systemd-run --user --scope`` can create a cgroup.
``shutil.which`` alone is insufficient: system services and containers may lack
the user D-Bus bus even with the binary on PATH (every spawn would fail with
``Failed to connect to user bus``), so a cheap probe is run and cached.

Use ``/bin/sh -c 'exit 0'``: NixOS provides ``/bin/sh`` but not ``/bin/true``
(#105365), regardless of the gateway service's PATH.NFúsystemd-runzhermes-probe-scope-Ú-:Né   Nz/bin/shz-czexit 0T)ÚstdinÚcapture_outputÚtimeoutrˆ   Úchecks   expand-environmentr+   z3systemd-run --user --scope probe failed (rc=%s): %sr:   Úreplacez*systemd-run --user --scope probe error: %s)r–   Ú_SYSTEMD_SCOPE_PROBE_LOCKr…   ÚshutilÚwhichrA   ÚgetpidÚuuidÚuuid4ÚhexÚrangeÚ
subprocessÚrunrl   ÚDEVNULLr�   Ú
returncoderj   ÚstderrrF   ÚdebugÚdecoderC   Ú	Exceptionr�   r‘   r’   r“   )ÚverdictÚ	availabler£   rc   Ú
probe_unitÚ_attemptÚresultÚexcs           r)   Ú!_systemd_run_user_scope_availabler¸     s¥  € ô $Ó%€GØÒØˆ÷ 
#Ö	"Ü'Ó)ˆØÒØ÷ 
#Ò	"ð ˆ	ßŒ9ðPÛàŸ™ mÓ4�ß�6à#6´r·y²y³{°mÀ1ÄTÇZÂZÃ\×EUÑEUÐVXÕEYÐDZÐ![�JÜ$)¨!¦H˜Ü!+§¢Ü/°ÀIÈtÐU]Ó^Ü",×"4Ñ"4ÀTØ$%Ü 4Ó 6Ø"'ô"˜ð !'× 1× 1Ð 1×6LÓ6LØ$9¸f¿m¹m×>RÐ>RÈsÔ$SÙ!à16Ò.ñ %-ð !'× 1Ñ 1°QÑ 6�Iß$ÜŸ™ØQØ"×-Ñ-°·±×0DÐ0DÀ×/LÑ/LÈWÐV_Ó/`×/fÑ/fÓ/hôð $-Ð Ü#'§>¢>Ó#3Ð Ø÷I 
#Ò	"øô@ ô PÜ—‘ÐIÈ3×OÑOûðPú÷A 
#×	"Ð	"úsY   ŸG/ºG/Á
GÁ(B(GÄGÄ%%GÅ-GÅ9%GÆG/ÇG,ÇG'Ç"G/Ç'G,Ç,G/Ç/H 	c                ó$   € V ^8„  d   QhR\         /# r%   r˜   )r(   s   "r)   r*   r*   6  s   € ÷ ñ ¬ñ r+   c                 ó"  € \         P                  P                  R4      R8w  d   R#  ^ RIHp  ^ RIHp V ! 4       ;'       d     V! RR7      \         P                  ! 4       8H  #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)	u  Whether this process is the live, supervised Hermes gateway itself.
Supervisor markers and ``_HERMES_GATEWAY`` are inherited by every descendant (and
importing ``gateway.run`` sets the latter), so also require ownership of the live
gateway PID file â€” scopes are for the gateway, not terminal children or CLIs.
Reads the launch marker (``HERMES_SUPERVISED_CHILD`` included), not the restart-route
probe: a Windows Scheduled-Task gateway sets only that marker, and the self-kill guards
gated here must protect it too (#113667).Ú_HERMES_GATEWAYÚ1F)Úis_supervised_gateway_launch)Úget_running_pid)Úcleanup_stalez8Could not verify supervised gateway process identity: %sN)rA   r„   r†   Úgateway.restartr½   Úgateway.statusr¾   r¥   r±   rF   r¯   )r½   r¾   r·   s      r)   Ú_is_supervised_gateway_processrÂ   6  sq   € ô 
‡z�z‡~�~Ð'Ó(¨CÔ/ÙðÝ@Ý2á+Ó-×eÐe±/ÐPUÔ2VÔZ\×ZcÒZcÓZeÑ2eÐeøÜô Ü�‰ÐOÐQTÔUÝûðús   ¨A" ÁA" Á"BÁ-B	Â	Bc                óh   € V ^8„  d   QhR\         \        ,          R\        R\         \        ,          /# )r&   Ú
shell_argvÚunit_suffixr'   )rg   rf   )r(   s   "r)   r*   r*   J  s.   € ÷ Tñ T¬$¬s­)ð TÄ#ð TÌ$ÌsÍ)ñ Tr+   c                óZ   € ^ RI pVP                  R4      pVf   V # \        VRV 2.V O5!  # )a;  Wrap *shell_argv* in a ``systemd-run --user --scope`` invocation with its own
memory accounting, so an OOM in the worker cannot kill the gateway cgroup.

``--collect`` makes the transient scope self-clean after exit; ``--unit`` gives it a recognisable name
for ``systemctl --user status`` / journalctl. See #70716.
Nrš   úhermes-worker-)r£   r¤   rl   )rÄ   rÅ   r£   rc   s   &&  r)   Ú_build_systemd_scope_argvrÈ   J  s9   € ó à�\‰\˜-Ó(€FØ‚~àÐÜ˜v¨¸°}Ð'EÐSÈ
ÓSÐSr+   Fc                   ó   € ] tR tRtRtRtR# )ÚRestartSafeScopeUnavailablei]  a.  A ``require_restart_safe_scope=True`` child could not get its transient scope.

Host-level (no user D-Bus / no ``systemd-run``), never a property of the
child being launched: callers that keep per-job retry budgets must not
charge it (a kanban card parked ``blocked`` for an unreachable bus, #114720).
r/   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r/   r+   r)   rÊ   rÊ   ]  s   † õr+   rÊ   c                ó4   € V ^8„  d   QhR\         R\         RR/# )r&   ÚdetailÚconsequencer'   N©rf   )r(   s   "r)   r*   r*   f  s!   € ÷ 2ñ 2¤cð 2¼3ð 2À4ñ 2r+   c               óR   € \         '       d   R# Rs \        P                  RW4       R# )zˆWarn once per process: the condition is host-level and the probe verdict
is cached, so this would otherwise fire on every cron dispatch.NTz%s; %s)Ú_scope_degraded_warnedrF   rG   )rÒ   rÓ   s   &$r)   Ú_warn_scope_degraded_oncer×   f  s!   € ÷ ÓÙØ!ÐÜ
‡N�N�8˜VÖ1r+   zÜcron children are dispatched as direct external subprocesses without restart-safe cgroup isolation (killed if the gateway restarts mid-job). Set cron.require_restart_safe_scope=true in config.yaml to fail closed instead.a2  workers are spawned unmanaged inside this systemd unit's cgroup and will be KILLED when the unit exits (Type=oneshot dispatch timers lose every worker within a second). Give the unit's user a session bus (`loginctl enable-linger <user>`) so workers get their own scope, or set KillMode=process on the unit.c                   ó0   a € ] tR tRt o RtV 3R ltRtV tR# )ÚGatewayChildDispatchi}  uØ  How a managed-gateway child is launched.

``in_process``: not a managed systemd gateway, ``argv is command``, the caller
keeps its in-process path.  ``scoped``: ``argv`` is the systemd-run wrapper.
``degraded``: no user scope could be created; ``argv`` is the direct command but
the caller MUST still launch it as an external subprocess â€” the distinct mode
exists so this case can never collapse into ``in_process`` and recreate the
restart interruption #101940 closed.
c                óP   <€ V ^8„  d   Qh/ S[ R,          ;R&   S[S[,          ;R&   # )r&   Úmodere   )Ú
in_processÚscopedÚdegraded)r   rg   rf   )r(   Ú__classdict__s   "€r)   r*   Ú!GatewayChildDispatch.__annotate__}  s(   ø‡ ‚ ñ Ð4Õ
5Ñ5ñ ñ ‰s�)�Oò r+   r/   N)rË   rÌ   rÍ   rÎ   rÏ   Ú__annotate_func__rÐ   Ú__classdictcell__©rß   s   @r)   rÙ   rÙ   }  s   ø‡ € ñ÷ ƒ r+   rÙ   c                óR   € V ^8„  d   QhR\         \        \        3,          R\        /# )r&   Ú	spawn_envr'   ©r   rf   rs   )r(   s   "r)   r*   r*   Œ  s"   € ÷ ñ ¬$¬s´C¨x­.ð ¼Tñ r+   c                óè   € \        V 4      pVP                  RR4       R\        V4      9   d   R# \        ;_uu_ 4        Rs\
        P                  ! 4       sRRR4       R#   + '       g   i     R# ; i)au  After a ``systemd-run --user --scope`` wrapper exits before its child could start: True
when the user bus is gone (:func:`systemd_user_bus_env` derives nothing), in which case the
cached True verdict is replaced so the next dispatch re-probes and degrades instead of
consuming another occurrence on the same dead wrapper (#110803).

*spawn_env* is the environment the wrapper was launched with: re-deriving from it (minus the
bus address it carried) honours a configured ``XDG_RUNTIME_DIR`` exactly as the spawn did, so
an unrelated wrapper exit on a host whose bus lives outside ``/run/user/<uid>`` is not
misread as a lost bus.rƒ   NFT)r   Úpopr�   r¢   r�   r‘   r’   r“   )rå   r~   s   & r)   Úscoped_spawn_lost_user_busré   Œ  s^   € ô �I‹€HØ‡L�LÐ+¨TÔ2Ø!Ô%9¸(Ó%CÔCÙß	"Ö	"Ø#(Ð Ü#'§>¢>Ó#3Ð ÷ 
#ñ ÷ 
#Ö	"ñ ús   ¾A Á A1	Úoutlives_parentc          
      ój   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\        /# )r&   ÚcommandrÅ   Úrequire_restart_safe_scoperê   r'   )rg   rf   rs   rÙ   )r(   s   "r)   r*   r*   ¡  s:   € ÷ 52ñ 52Ü”#�Yð52Ü(+ð52ÜIMð52äð52ô ñ52r+   c               óª  a aa€ \         '       g   \        RS 4      # \        P                  P	                  R4      '       g   \        RS 4      # \        4       oS'       g   V'       g   \        RS 4      # R V VV3R llp\        4       '       g    V! R\        P                  ! 4        R24      # \        S VR7      pVS 8X  d	   V! R4      # \        R	V4      # )
u”  Place a managed-systemd gateway child outside the gateway cgroup.

A systemd-supervised gateway restart kills every process in the service
cgroup, so children that must survive it run in a transient user scope.
Hosts with no user systemd session (containers, LXCs without linger) cannot
create one; hard-failing there is a silent cron outage, so callers state the
policy: ``require_restart_safe_scope=True`` raises
:class:`RestartSafeScopeUnavailable` (kanban's long-lived workers), ``False``
degrades to a direct external subprocess with a once-per-process warning
(cron, behind ``cron.require_restart_safe_scope``).

``outlives_parent=True`` (fire-and-forget kanban workers): any *other*
systemd unit â€” a ``Type=oneshot`` dispatch timer, an operator's sequencer
service â€” tears its cgroup down when it exits, so the child is scope-wrapped
there too (#113612). Whether that unit actually kills its children
(``KillMode``, lifetime) is not knowable here, so without a user bus it
degrades with a loud warning instead of refusing: a long-lived
``Type=simple`` sequencer without linger keeps working. A cron job blocks its
caller until it finishes and never needs this.
rÜ   ÚINVOCATION_IDc                ó0   € V ^8„  d   QhR\         R\        /# )r&   rÒ   r'   )rf   rÙ   )r(   s   "r)   r*   Ú5restart_safe_gateway_child_argv.<locals>.__annotate__Á  s   € ÷ 
9ñ 
9œð 
9Ô!5ñ 
9r+   c                 óª   <€ S'       d,   S'       d   \        R V  24      h\        RV  2\        R7       M\        RV  2\        R7       \	        RS4      # )z<cannot create restart-safe systemd scope for gateway child: zmanaged gateway: )rÓ   zsystemd unit dispatch: rÞ   )rÊ   r×   Ú_CRON_DEGRADED_CONSEQUENCEÚ_UNIT_DEGRADED_CONSEQUENCErÙ   )rÒ   rì   rí   Úsupervised_gateways   &€€€r)   Ú_degradeÚ1restart_safe_gateway_child_argv.<locals>._degradeÁ  sW   ø€ ßß)ä1ØRÐSYÐRZÐ[óð ô &Ð(9¸&¸Ð&BÔPjÖkä%Ð(?À¸xÐ&HÔVpÕqÜ# J°Ó8Ð8r+   z`systemd-run --user --scope is unavailable (usually no reachable user D-Bus session at /run/user/zs/bus). On a system-level service install, run `sudo loginctl enable-linger <gateway-user>` and restart the gateway.©rÅ   z4systemd-run disappeared after the availability proberÝ   )	r…   rÙ   rA   r„   r†   rÂ   r¸   ro   rÈ   )rì   rÅ   rí   rê   rö   rÝ   rõ   s   f$d$  @r)   Úrestart_safe_gateway_child_argvrù   ¡  s¿   ú€ ÷0 ‹9Ü# L°'Ó:Ð:Ü�:‰:�>‰>˜/×*Ò*Ü# L°'Ó:Ð:Ü7Ó9Ðß§oÜ# L°'Ó:Ð:÷
9ò 
9ô -×.Ò.ÙðÜŸš›˜ð &TðTó
ð 	
ô
 ' w¸KÔH€FØ�ÔÙÐNÓOÐOÜ ¨&Ó1Ð1r+   c                ó0   € V ^8„  d   QhR\         R\        /# )r&   rd   r'   ©rf   rs   )r(   s   "r)   r*   r*   Ù  s   € ÷  ñ  ¤#ð  ¬$ñ  r+   c           	     ó^  a€ ^ RI pVP                  R4      pVf   R#  \        P                  ! VRRV .R^\        P                  \        4       RR7      pVP                  ^ 8w  dš   VP                  ;'       g    RP                  R	R
7      P                  4       o\        ;QJ d    V3R lR 4       F  '       g   K   RM	  RM! V3R lR 4       4      '       d   R# \        P                  RWP                  S4       R# R#   \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)uP  Stop a transient systemd user scope by unit name.
Reaps the *entire* cgroup â€” catching double-forked descendants reparented to init
inside the scope that survive a plain PID signal (SIGTERM all, SIGKILL after
``TimeoutStopSec``). True if stopped or already gone; False if ``systemctl`` is
unavailable or the stop failed.

See #70716.
NÚ	systemctlFri   ÚstopT)rž   rŸ   r�   rˆ   r    r+   r¡   ©Úerrorsc              3   óH   <"  € T F  qSP                  4       9   x € K  	  R # 5i©N)Úlower)Ú.0Úmarkerr®   s   & €r)   Ú	<genexpr>Ú%_stop_systemd_unit.<locals>.<genexpr>ò  s   øé € ÐhÑ:g°˜VŸ\™\›^Ö+Ó:gùs   ƒ"z&systemctl --user stop %s exited %d: %sz#systemctl --user stop %s failed: %s)z
not loadedz	not foundzdoes not exist)r£   r¤   rª   r«   r¬   r�   r­   r®   r°   rC   ÚanyrF   r¯   r±   )rd   r£   rc   r¶   r·   r®   s   &    @r)   Ú_stop_systemd_unitr	  Ù  só   ø€ ó à�\‰\˜+Ó&€FØ‚~ÙðÜ—’Ø�X˜v yÐ1ØØÜ×$Ñ$Ü$Ó&Øô
ˆð ×Ñ Ô!Ø—m‘m×*Ð* s×2Ñ2¸)Ð2ÓD×JÑJÓLˆFß‹sÔhÑ:gÓh�s�sŠsÔhÑ:gÓh×hÒhÙÜ�L‰LÐAÀ9×N_ÑN_ÐagÔhÙÙøÜô Ü�‰Ð:¸IÔKÝûðús0   žAD  Á8+D  Â$D  Â;D  Ã!D  Ä D,ÄD'Ä'D,c                ó0   € V ^8„  d   QhR\         R\        /# )r&   Úsecondsr'   ©r6   rf   )r(   s   "r)   r*   r*   ü  s   € ÷ ñ ¤ð ¬ñ r+   c                 óª   € \        ^ \        V 4      4      pV^<8  d   V R2# \        V^<4      w  r#V^<8  d	   V RV R2# \        V^<4      w  rBV RV R2# )é    Úszm zh Úm)rS   r6   Údivmod)r  r  ÚminsÚsecsÚhourss   &    r)   Úformat_uptime_shortr  ü  sl   € ÜˆAŒs�7‹|Ó€AØˆ2„vØ��AˆwˆÜ˜˜2“�J€DØˆb„yØ��r˜$˜˜qÐ!Ð!Ü˜˜rÓ"�K€EØˆW�B�t�f˜AÐÐr+   c                ó0   € V ^8„  d   QhR\         R\        /# ©r&   Ú
session_idr'   ©rf   r   )r(   s   "r)   r*   r*     s   € ÷ Pñ Pœ3ð P¤4ñ Pr+   c                 ó   € R RRRV  2/# )ÚstatusÚ	not_foundÚerrorzNo process with ID r/   )r  s   &r)   Ú
_not_foundr    s   € Ø�k 7Ð.AÀ*ÀÐ,NÐOÐOr+   c                ó4   € V ^8„  d   QhRRR\         R\        /# )r&   ÚsessionÚProcessSessionÚnr'   r  )r(   s   "r)   r*   r*     s"   € ÷ 2ñ 2Ð*ð 2¬sð 2´sñ 2r+   c                ó:   € ^ RI Hp V! V P                  V) R 4      # )zBLast *n* chars of the session output with ANSI sequences stripped.©Ú
strip_ansiN)Útools.ansi_stripr%  Úoutput_buffer)r   r"  r%  s   && r)   Ú_output_tailr(    s   € å+á�g×+Ñ+¨Q¨B¨CÐ0Ó1Ð1r+   c                ó(   € V ^8„  d   QhRRR\         /# )r&   r   r!  r'   ©r   )r(   s   "r)   r*   r*     s   € ÷ `ñ `Ð 0ð `´Tñ `r+   c                ó¤   € V P                   ;'       g    \        p\        V P                  4      V,
          pR\	        W4      /V^ 8”  d   RV/C# / C# )a[  ``output`` sized by the session's ``completion_output_chars`` plus ``output_cut`` when trimmed.

Shared by the completion notification AND the wait/poll/kill snapshots: a bot in an api_server
or one-shot session cannot receive notifications and polls instead, so the polled result must
carry the same whole reply and the same cut marker (#115334).ÚoutputÚ
output_cut)Úcompletion_output_charsÚCOMPLETION_OUTPUT_CHARSÚlenr'  r(  )r   ÚlimitÚcuts   &  r)   Ú_completion_outputr3    sW   € ð ×+Ñ+×FÐFÔ/F€EÜ
ˆg×#Ñ#Ó
$ uÕ
,€CØ”l 7Ó2Ð_ÈcÐTUÌg¸ÀcÐ7JÐ_Ð_Ð[]Ð_Ð_r+   c                   ó®  a € ] tR tRt o RtRtRtRtRtRt	Rt
RtRtRtRtRtRtRtRtRt]tRtRtRtRtRtRtRtRtRtRtRt Rt!Rt"^ t#Rt$Rt%^ t&]'! ](R	7      t)^ t*^ t+]'! RRR
7      t,]'! ^ RR
7      t-]'! ^ RR
7      t.]'! ^ RR
7      t/]'! ^ RR
7      t0]'! RRR
7      t1]'! RRR
7      t2]'! RRR
7      t3]'! ^ RR
7      t4]'! ]5Pl                  RR7      t7]'! RRR
7      t8]'! RRR
7      t9]'! ]5Pt                  R	7      t;]'! RRR
7      t<]'! ]5Pl                  RR7      t=]'! RRR
7      t>]'! RRR
7      t?R t@V 3R lR ltAV 3R lR ltBV 3R lR ltCRV 3R lR lltDV 3R ltERtFV tGR# )r!  i  z3A tracked background process with output buffering.r9   Nr3   FÚexitedÚhost)Údefault_factory)ÚdefaultÚrepr)r7  r9  c                óP   € V P                   '       g   V P                  V n         R # R # r  )Úowner_task_idÚtask_id©Úselfs   &r)   Ú__post_init__ÚProcessSession.__post_init__d  s!   € ð ×!×!Ð!Ø!%§¡ˆDÖñ "r+   c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r&   Útextr'   NrÔ   )r(   rß   s   "€r)   r*   ÚProcessSession.__annotate__j  s   ø€ ÷ &ñ &¡#ð &¨$ñ &r+   c                óŠ   € V P                   ;_uu_ 4        V P                  V4       RRR4       R#   + '       g   i     R# ; i)zMAppend to the rolling output buffer under the session lock, keeping the tail.N)Ú_lockÚ_append_locked©r>  rC  s   &&r)   Úappend_outputÚProcessSession.append_outputj  s%   € à�Z�Z‹ZØ×Ñ Ô%÷ �Z�ZŠZús	   •1±A	c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r&   rC  r'   rû   )r(   rß   s   "€r)   r*   rD  o  s   ø€ ÷ ñ ©Sð ±Tñ r+   c                óÄ   € V P                   ;_uu_ 4        V P                  '       d    RRR4       R# V P                  V4       RRR4       R#   + '       g   i     R# ; i)zÉAppend unless the session has exited. Decided under the lock a kill holds while it
snapshots the output and sets ``exited``, so a chunk is either in the kill's receipt or
dropped, never added after it.NFT)rF  r5  rG  rH  s   &&r)   Úappend_output_if_runningÚ'ProcessSession.append_output_if_runningo  sG   € ð �Z�Z‹ZØ�{�{ˆ{Ø÷ ‰Zð ×Ñ Ô%÷ ñ ÷	 ŽZñ ús   •A³AÁA	c                ó$   <€ V ^8„  d   QhRS[ RR/# rB  rÔ   )r(   rß   s   "€r)   r*   rD  y  s   ø€ ÷ Mñ M¡3ð M¨4ñ Mr+   c                ó  € V ;P                   V,          un         V ;P                  \        V4      ,          un        \        V P                   4      V P                  8”  d"   V P                   V P                  ) R  V n         R # R # r  )r'  Útotal_output_charsr0  Úmax_output_charsrH  s   &&r)   rG  ÚProcessSession._append_lockedy  se   € Ø×Ò˜dÕ"ÕØ×Ò¤3 t£9Õ,ÕÜˆt×!Ñ!Ó" T×%:Ñ%:Ô:Ø!%×!3Ñ!3°T×5JÑ5JÐ4JÐ4KÐ!LˆDÖñ ;r+   c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r&   ÚreasonÚsourcer'   NrÔ   )r(   rß   s   "€r)   r*   rD    s#   ø€ ÷ 1ñ 1©Sð 1ÁSð 1ÐRVñ 1r+   c                ór   € RV n         V P                  R8w  d   Wn        W n        V'       d	   W0n        R# R# R# )zmRecord an exit. A kill that raced the observer already recorded its own
exit_code/reason; never overwrite it.TÚkilledN)r5  Úcompletion_reasonÚ	exit_codeÚtermination_source)r>  r[  rV  rW  s   &&&&r)   Úmark_exitedÚProcessSession.mark_exited  s7   € ð ˆŒØ×!Ñ! XÔ-Ø&ŒNØ%+Ô"ßØ*0Ö'ñ ñ .r+   c                ó‚  <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[S[,          ;R&   S[S[P                  ,          ;R&   S[;R&   S[S[ ,          ;R	&   S[;R
&   S[S[,          ;R&   S[;R&   S[;R&   S[S[,          ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[;R&   S[;R&   S[ ;R&   S[ ;R&   S[;R&   S[ ;R&   S[;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[;R &   S[ ;R!&   S[;R"&   S[;R#&   S[S[ ,          ;R$&   S[;R%&   S[;R&&   S[;R'&   S[;R(&   S[;R)&   S[;R*&   S[;R+&   S[;R,&   S[;R-&   S[;R.&   S[;R/&   S[	P                  ;R0&   S[;R1&   S[;R2&   S[	P                  ;R3&   S[S[	P                  ,          ;R4&   S[	P                  ;R5&   S[;R6&   S[;R7&   # )8r&   Úidrì   r<  r;  Úsession_keyÚpidÚprocessÚenv_refÚcwdÚ
started_atÚhost_start_timer5  Ú	exited_atr[  rZ  r\  r'  rS  ÚdetachedÚ	pid_scopeÚsystemd_unitÚ	wsl_chainÚhandoff_noteÚpersist_on_releaseÚ
output_logÚwatcher_platformÚwatcher_chat_idÚwatcher_user_idÚwatcher_user_nameÚwatcher_thread_idÚwatcher_message_idÚwatcher_intervalÚparent_session_idÚnotify_on_completer.  Úwatch_patternsÚheartbeat_secondsrR  Ú_heartbeat_lastÚ_heartbeat_total_at_lastÚ_heartbeat_seqÚ_watch_hitsÚ_watch_suppressedÚ_watch_disabledÚ_watch_cooldown_untilÚ_watch_strike_candidateÚ_watch_consecutive_strikesÚ_completion_eventÚ_finish_claimedÚ_scope_stop_pendingrF  Ú_reader_threadÚ_reader_finish_requestedÚ_reader_selectableÚ_pty)rf   r   r6   rª   ÚPopenr   Úfloatrs   rg   Ú	threadingÚEventÚLockÚThread)r(   rß   s   "€r)   r*   rD    s@  ø‡ ‚ ñ 	�Gñ ñ �Lñ	 ñ
 Ññ ñ Ññ ñ Ññ ñ 
‘#�Ññ ñ ‘j×&Ñ&Õ'Ñ.ñ ñ Ññ ñ 
‘#�Ññ ñ Ññ ñ ™c•]Ñ)ñ ñ  Ññ! ñ" Ññ# ñ$ ™�}Ñ#ñ% ñ& Ñ%ñ' ñ( Ñ ñ) ñ* Ññ+ ñ, Ñ,ñ- ñ. Ññ/ ñ0 Ññ1 ñ2 Ññ3 ñ4 Ññ5 ñ8 Ññ9 ñ: Ñ$ñ; ñ> Ññ? ñB ÑñC ñD ÑñE ñF ÑñG ñH ÑñI ñJ ÑñK ñL Ñ ñM ñN ÑñO ñT ÑñU ñV Ñ$ñW ñX !Ñ$ñY ñZ ™•IÑ;ñ[ ñ\ Ññ] ñ^ Ññ_ ñ` Ñ;ña ñb "Ñ@ñc ñd Ñ6ñe ñf Ñ3ñg ñh Ñ9ñi ñj Ñ<ñk ñn !ÑAño ñp "ÑDñq ñr !$ÑBñs ñt !—‘Ñ[ñu ñz Ñ<ñ{ ñ@ Ñ@ñA ñB �>‰>ÑAñC ñD ™Y×-Ñ-Õ.ÑPñE ñF (Ÿo™oÑbñG ñH Ñ?ñI ñJ Ñ/òK r+   )rZ  r[  r5  r'  r;  r\  ©r5  r9   )HrË   rÌ   rÍ   rÎ   rÏ   r<  r;  ra  rb  rc  rd  re  rf  rg  r5  rh  r[  rZ  r\  r'  ÚMAX_OUTPUT_CHARSrS  ri  rj  rk  rl  rm  rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  r.  r   rg   ry  rz  rR  r{  r|  r}  r~  r  r€  r�  r‚  rƒ  r�  rŽ  r„  r…  r†  r�  rF  r‡  rˆ  r‰  rŠ  r?  rI  rN  rG  r]  rá   rÐ   râ   rã   s   @r)   r!  r!    sï  ø‡ € á=ð €Gà€Mà€KØ€CØ*.€GØ€GØ€CØ€JØ%)€OØ€FØ€IØ#€IØ%ÐØ ÐØ€MØ,ÐØ€HØ€IØ€LØ€Ià€LØ$Ðà€JàÐØ€OØ€OØÐØÐØ ÐØÐð  ÐØ$ÐØ#$ÐÙ %°dÔ ;€NØÐØÐÙ"¨3°UÔ;€OÙ$)°!¸%Ô$@ÐÙ¨°Ô6€NÙ Q¨UÔ3€KÙ"¨1°5Ô9ÐÙ!¨%°eÔ<€Oá#(°¸5Ô#AÐÙ$)°%¸eÔ$DÐÙ&+°A¸EÔ&BÐÙ).¸y¿¹ÐUZÔ)[Ðñ "¨%°eÔ<€Oñ !&¨e¸%Ô @ÐÙ!°)·.±.ÔA€EÙ16¸tÈ%Ô1P€NÙ05ÀiÇoÁoÐ\aÔ0bÐÙ$¨U¸Ô?ÐÙ˜d¨Ô/€Dò.÷&ð &÷
ð ÷Mð M÷1ò 1÷E ƒ r+   r!  r<  c              #   ó,   "  € T F
  pR V 2x € K  	  R# 5i)Úwatcher_Nr/   )r  Úks   & r)   r  r  ‘  s   é € Ð2Ñ1˜ˆ��…nÓ1ùs   ‚rv  rw  rx  r.  ry  rz  rn  ro  z¶Spawned via a wsl[.exe] launcher: the recorded host PID is the short-lived launcher, not the Linux-side workers. Inspect them with `wsl -e ps` / `wsl --list --running` from the host.c            
       ój  a € ] tR tRt o RtR»tRtR tV 3R lR ltV 3R lR lt	V 3R	 lR
 lt
V 3R lR lt]V 3R lR l4       tV 3R lR ltV 3R lR ltV 3R lR lt]V 3R lR l4       t]V 3R lR l4       tV 3R lR lt]V 3R lR l4       t]V 3R lR l4       t]V 3R lR  l4       tV 3R! lR" ltV 3R# lR$ ltV 3R% lR& ltV 3R' lR( ltV 3R) lR* lt]V 3R+ lR, l4       t]V 3R- lR. l4       t]V 3R/ lR0 l4       t]V 3R1 lR2 l4       t ]V 3R3 lR4 l4       t!V 3R5 lR6 lt"]V 3R7 lR8 l4       t#R¼V 3R9 lR: llt$V 3R; lR< lt%R½V 3R? lR@ llt&V 3RA lRB lt'RCR>RDR>RER>RFR>RGRH/V 3RI lRJ llt(R¾V 3RK lRL llt)V 3RM lRN lt*V 3RO lRP lt+]! ],4      t-V 3RQ lRR lt.V 3RS lRT lt/RUR/V 3RV lRW llt0R¿V 3RX lRY llt1V 3RZ lR[ lt2V 3R\ lR] lt3]V 3R^ lR_ l4       t4V 3R` lRa lt5]V 3Rb lRc l4       t6V 3Rd lRe lt7V 3Rf lRg lt8RÀRhR=RiRj/V 3Rk lRl lllt9]V 3Rm lRn l4       t:RoRH/V 3Rp lRq llt;]V 3Rr lRs l4       t<]V 3Rt lRu l4       t=V 3Rv lRw lt>RÁRoRH/V 3Rx lRy lllt?^t@V 3Rz lR{ ltAV 3R| lR} ltBV 3R~ lR ltC]V 3R€ lR� l4       tDV 3R‚ lRƒ ltERÂV 3R„ lR… lltFRÀV 3R† lR‡ lltG]V 3Rˆ lR‰ l4       tHRŠR‹RŒRH/V 3R� lRŽ lltI]V 3R� lR� l4       tJV 3R‘ lR’ ltKV 3R“ lR” ltLV 3R• lR– ltMRÃV 3R— lR˜ lltNV 3R™ lRš ltOV 3R› lRœ ltPV 3R� lRž ltQRÄRŸR/V 3R  lR¡ llltRV 3R¢ lR£ ltSV 3R¤ lR¥ ltTV 3R¦ lR§ ltUV 3R¨ lR© ltVRªR>/V 3R« lR¬ lltWRÀV 3R­ lR® lltXV 3R¯ lR° ltYV 3R± lR² ltZ][! 0 RÅm4      t\V 3R´ lRµ lt]RÀR¶][! 4       RŠR³RŒR/V 3R· lR¸ lllt^R¹ t_Rºt`V taR=# )ÆÚProcessRegistryi¢  zÙIn-memory registry of running and finished background processes.
Thread-safe: accessed from executor threads (terminal_tool, process handlers),
the gateway asyncio loop (watchers, reset checks) and the cleanup thread.Fc                óp  € / V n         / V n        \        P                  ! 4       V n        . V n        ^ RIpVP                  4       V n        ^ RI	p\        4       V n        \        4       V n        \        P                  ! 4       V n        R;V n        V n        ^ ;V n        V n        RV n        RV n        RV n        R# )r  Nr3   )Ú_runningÚ	_finishedr�  r�  rF  Úpending_watchersÚqueueÚQueueÚcompletion_queueÚtools.async_delegationÚsetÚ_completion_consumedÚ_poll_observedÚ_global_watch_lockÚ_global_watch_window_startÚ_global_watch_tripped_untilÚ_global_watch_window_hitsÚ$_global_watch_suppressed_during_tripÚ	on_outputÚon_closeÚ_heartbeat_thread)r>  Ú
_queue_modÚtoolss   &  r)   Ú__init__ÚProcessRegistry.__init__®  s    € Ø35ˆŒØ46ˆŒÜ—^’^Ó%ˆŒ
à68ˆÔó 	#Ø2<×2BÑ2BÓ2DˆÔó 	&ô *-«ˆÔ!ô $'£5ˆÔä"+§.¢.Ó"2ˆÔØMPÐPˆÔ'¨$Ô*JØUVÐVˆÔ&¨Ô)Rð ˆŒØˆŒØ=AˆÖr+   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r&   r   r  r'   )r!  r6   )r(   rß   s   "€r)   r*   ÚProcessRegistry.__annotate__Õ  s"   ø€ ÷ 	ñ 	¡^ð 	¹cð 	Ácñ 	r+   c                ó˜   € \        \        V4      \        4      pW!n        \        P                  ! 4       Vn        V P                  4        V# )zQEnable periodic heartbeat events for ``session``; returns the effective interval.)rS   r6   ÚHEARTBEAT_MIN_SECONDSrz  r‘   r{  Ú_ensure_heartbeat_thread)r>  r   r  s   &&&r)   Úarm_heartbeatÚProcessRegistry.arm_heartbeatÕ  s:   € ä”c˜'“lÔ$9Ó:ˆØ$+Ô!Ü"&§)¢)£+ˆÔð 	×%Ñ%Ô'Øˆr+   c                ó   <€ V ^8„  d   QhRR/# ©r&   r'   Nr/   )r(   rß   s   "€r)   r*   r°  à  s   ø€ ÷ +ñ +¨$ñ +r+   c                ó^  € V P                   ;_uu_ 4        V P                  e,   V P                  P                  4       '       d    R R R 4       R # \        P                  ! V P
                  RRR7      V n        V P                  P                  4        R R R 4       R #   + '       g   i     R # ; i)Nzprocess-heartbeatT)ÚtargetÚnameÚdaemon)rF  rª  Úis_aliver�  r�  Ú_heartbeat_loopÚstartr=  s   &r)   r³  Ú(ProcessRegistry._ensure_heartbeat_threadà  sw   € Ø�Z�Z‹ZØ×%Ñ%Ò1°d×6LÑ6L×6UÑ6U×6WÒ6WØ÷ ‰Zô &/×%5Ò%5Ø×+Ñ+Ð2EÈdô&TˆDÔ"à×"Ñ"×(Ñ(Ô*÷ �Z�ZŠZús   •.BÁBÁABÂB,	c                ó   <€ V ^8„  d   QhRR/# r·  r/   )r(   rß   s   "€r)   r*   r°  è  s   ø€ ÷ 3ñ 3 ñ 3r+   c                óê  €  \         P                  ! \        4       \         P                   ! 4       pV P                  ;_uu_ 4        V P                  P                  4        Uu. uFO  pVP                  ^ 8”  g   K  VP                  '       d   K*  WP                  ,
          VP                  8¼  g   KM  VNKQ  	  ppRRR4       X F  pV P                  WA4       K  	  KÜ  u upi   + '       g   i     L1; i)zœOne daemon thread for every heartbeat session: reader threads block on the pipe and
cannot keep time, and a per-process timer would leak one thread per job.N)
r‘   ÚsleepÚHEARTBEAT_TICK_SECONDSrF  r™  Úvaluesrz  r5  r{  Ú_emit_heartbeat)r>  Únowr  Úduer   s   &    r)   r½  ÚProcessRegistry._heartbeat_loopè  s¹   € ð Ü�JŠJÔ-Ô.Ü—)’)“+ˆCØ——“Ø"&§-¡-×"6Ñ"6Ô"8ó KÑ"8˜QØ×-Ñ-°Ñ1ô Ø:;¿(½(ô à×!2Ñ!2Õ2°a×6IÑ6IÑI÷ �qÑ"8�ð K÷ ó �Ø×$Ñ$ WÖ2ó ùòK÷ —ús0   ÁC"Á"CÁ:CÂCÂ1CÂ7C"ÃC"Ã"C2	c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r&   r   rÆ  r'   N)r!  rŒ  )r(   rß   s   "€r)   r*   r°  õ  s"   ø€ ÷ 0ñ 0¡~ð 0¹Eð 0Àdñ 0r+   c                óˆ  € W!n         VP                  ;_uu_ 4        VP                  VP                  ,
          pV^ 8”  d   VP                  V) R MRpVP                  Vn        RRR4       X'       g   R# \        V4      w  rEV;P                  ^,          un        / V P                  V4      CRRRVP                  RVP                  RVP                  '       d   \        W!P                  ,
          4      M^ RVR	VR
VP                  /Cp\        V4       V P                  P                  V4       R#   + '       g   i     LÖ; i)a  Queue a heartbeat carrying the output since the last one. A tick with nothing new is
skipped outright: every queued event costs the owner a full model turn, and "still running,
no output" is already visible on the process surfaces (status stack, /agents dock).Nr9   ÚtypeÚ	heartbeatÚseqÚintervalÚelapsedr,  Úomittedrf  )r{  rF  rR  r|  r'  r   r}  Ú_watch_event_baserz  rf  r6   Ú_redact_process_resultrž  Úput)r>  r   rÆ  Údeltar,  rÐ  Únotifications   &&&    r)   rÅ  ÚProcessRegistry._emit_heartbeatõ  s  € ð #&ÔØ�]�]‹]Ø×.Ñ.°×1QÑ1QÕQˆEØ7<¸q´y�W×*Ñ*¨E¨6¨7Ñ3ÀbˆFØ/6×/IÑ/IˆGÔ,÷ ÷ ÙÜ/°Ó7‰ˆØ×Ò !Õ#Õð	
Ø×$Ñ$ WÓ-ð	
à�KØ�7×)Ñ)Ø˜×1Ñ1Ø¸×8J×8JÐ8J”s˜3×!3Ñ!3Õ3Ô4ÐPQØ�fØ�wØ˜'×,Ñ,ñ	
ˆô 	˜|Ô,Ø×Ñ×!Ñ! ,Ö/÷' �]ús   ›AD1Ä1E	c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rL  rÔ   )r(   rß   s   "€r)   r*   r°    s   ø€ ÷  ñ  ¡ð  ©ñ  r+   c                ó6  a€ V P                  R4      oS'       dp   \        ;QJ d-    V3R l\        P                   4       F  '       g   K   RM"	  RM! V3R l\        P                   4       4      '       d   SP	                  ^ 4       Kw  RP                  S4      # )z:Strip shell startup warnings from the beginning of output.Ú
c              3   ó:   <"  € T F  qS^ ,          9   x € K  	  R# 5i)r  Nr/   )r  ÚnoiseÚliness   & €r)   r  Ú5ProcessRegistry._clean_shell_noise.<locals>.<genexpr>  s   øé € ÐcÑ;b°% U¨1¥XÖ-Ó;bùs   ƒTF)Úsplitr  r—  Ú_SHELL_NOISE_SUBSTRINGSrè   Újoin)rC  rÜ  s   &@r)   Ú_clean_shell_noiseÚ"ProcessRegistry._clean_shell_noise  s\   ø€ ð —
‘
˜4Ó ˆßŸ›Ôc¼?×;bÒ;bÓcŸŸšÔc¼?×;bÒ;bÓc×cÒcØ�I‰I�aŽLØ�y‰y˜ÓÐr+   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r&   r   Úchunkr'   N©r!  rf   )r(   rß   s   "€r)   r*   r°    s"   ø€ ÷ !ñ !¡Nð !¹3ð !À4ñ !r+   c                ó²   € V P                   pVe	   V'       g   R# \        \        4      ;_uu_ 4        V! W4       RRR4       R#   + '       g   i     R# ; i)zRForward a chunk to the live-output sink; called from reader threads, never raises.N)r¨  r   r±   )r>  r   rä  Úsinks   &&& r)   Ú_emit_outputÚProcessRegistry._emit_output  s7   € à�~‰~ˆØŠ<ŸuÙÜ”i× Õ Ù�Ô ÷ !× × Ò ús   ²	AÁA	c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r&   r   Únew_textr'   Nrå  )r(   rß   s   "€r)   r*   r°    s'   ø€ ÷ Hñ H©^ð HÁsð HÈtñ Hr+   c           
     ó(  a€ VP                   '       d   VP                  '       d   R# VP                  '       d   R# VP                  4        Uau. uFˆ  o\        ;QJ d)    V3R lVP                    4       F  '       g   K   RM	  RM! V3R lVP                    4       4      '       g   KY  \        V3R lVP                    4       4      SP                  4       3NKŠ  	  ppV'       g   R# V^ ,          ^ ,          pV UUu. uF  w  rcVNK	  	  ppp\        P                  ! 4       pVP                  ;_uu_ 4        VP                  '       dÓ   W�P                  8  dÃ   V;P                  \        V4      ,          un
        VP                  '       d    RRR4       R# RVn        V;P                  ^,          un        VP                  \        8  d    RRR4       R# RVn        RVn        V P!                  WP                  \         R\"         R24        RRR4       R# VP                  '       d   VP                  '       g   ^ Vn        RVn        V\"        ,           Vn	        V;P$                  ^,          un        VP                  p	^ Vn
        VP$                  \&        8¬  p
V
'       d   RVn        RVn        RRR4       RP)                  VR	,          4      p\        V4      R
8”  d   VR,          R,           pV P+                  V4      '       dD   / V P-                  V4      CRRRVRVRX	/Cp\/        V4       V P0                  P3                  V4       X
'       d   V P!                  V^ R\&         R24       R# R# u upi u uppi   + '       g   i     LÔ; i)aS  Scan a freshly-read chunk for watch patterns and queue notifications.
Per-session rate limiting (see WATCH_* constants): one match per cooldown
window, a match inside the window is one strike, WATCH_STRIKE_LIMIT consecutive
strikes or WATCH_LIFETIME_MAX_HITS total deliveries disable watching and
promote the session to notify_on_complete.Nc              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir  r/   ©r  ÚprZ   s   & €r)   r  Ú8ProcessRegistry._check_watch_patterns.<locals>.<genexpr>-  s   øé € Ð4_ÑH^À1¸$¶YÓH^ùs   ƒTFc              3   ó8   <"  € T F  qS9   g   K  Vx € K  	  R # 5ir  r/   rî  s   & €r)   r  rð  ,  s   øé € ÐAÑ3˜¸D±y—!’!Ó3ùs   ƒ�
z7 consecutive rate-limit windows triggered (min spacing zs). rÙ  :Né   Nr1   :NiÐ  Nz
...(truncated)rË  Úwatch_matchÚpatternr,  Ú
suppressedzreached the lifetime cap of z delivered matches. )ry  r€  r5  rI   r  ÚnextÚrstripr‘   rF  r�  r  r0  r‚  rƒ  ÚWATCH_STRIKE_LIMITrx  Ú_emit_watch_disabledÚWATCH_MIN_INTERVAL_SECONDSr~  ÚWATCH_LIFETIME_MAX_HITSrà  Ú_global_watch_admitrÑ  rÒ  rž  rÓ  )r>  r   rë  rZ   ÚhitsÚmatched_patternÚ_Úmatched_linesrÆ  rõ  Úlifetime_exhaustedr,  rÕ  s   &&&`         r)   Ú_check_watch_patternsÚ%ProcessRegistry._check_watch_patterns  s   ø€ ð ×%×%Ð%¨×)@×)@Ð)@Ùð �>�>ˆ>Ùð !×+Ñ+Ô-ôaá-�·³Ô4_È×H^ÒH^Ó4_··²Ô4_È×H^ÒH^Ó4_×1_ô RŒTÔA˜W×3Ò3ÓAÓAÀ4Ç;Á;Ã=ÓQÙ-ð 	ð a÷ ÙØ˜q�' !�*ˆÙ-1Ô2©T¡' !›©TˆÑ2Ü�iŠi‹kˆØ�]�]‹]Ø×,×,Ð,°×7TÑ7TÔ1Tð ×)Ò)¬S°Ó-?Õ?Õ)Ø×2×2Ð2Ø÷ ‰]ð 37�Ô/Ø×2Ò2°aÕ7Õ2Ø×5Ñ5Ô8JÔJØ÷ ‰]ð +/�Ô'ð .2�Ô*Ø×)Ñ)Ø×6Ñ6Ü)Ð*ð +$Ü$>Ð#?¸tðEôFð ÷' ‰]ð, ×,×,Ð,°W×5T×5TÐ5TØ56�Ô2Ø.3ˆGÔ+à,/Ô2LÕ,LˆGÔ)Ø×Ò 1Õ$ÕØ ×2Ñ2ˆJØ()ˆGÔ%à!(×!4Ñ!4Ô8OÑ!OÐß!Ø*.�Ô'Ø-1�Ô*÷E ðF —‘˜=¨Õ-Ó.ˆÜˆv‹;˜ÔØ˜E•]Ð%7Õ7ˆFØ×#Ñ# C×(Ò(ðØ×(Ñ(¨Ó1ðà˜Ø˜?Ø˜&Ø˜jñˆLô # <Ô0Ø×!Ñ!×%Ñ% lÔ3çØ×%Ñ%Ø˜Ð:Ô;RÐ:SÐSgÐhöñ ùòsaùó 3ç�]úsP   ÁM6ÁM6Â %M6Â*3M6Ã>M;Ä7ANÆ6NÇ9NÈNÈ.NÉ A&NÊ'NÎN	c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r&   r   rõ  Úwhyr'   N)r!  r6   rf   )r(   rß   s   "€r)   r*   r°  i  s+   ø€ ÷ 
ñ 
©Nð 
Éð 
ÑRUð 
ÐZ^ñ 
r+   c                ó�   € V P                   P                  / V P                  V4      CRRRVRRVP                   RV R2/C4       R# )	zNQueue the one-shot watch_disabled summary (strike-limit or lifetime-cap path).rË  Úwatch_disabledrõ  Úmessagez$Watch patterns disabled for process u    â€” ziFalling back to notify_on_complete semantics; you'll get exactly one notification when the process exits.N)rž  rÓ  rÑ  r`  )r>  r   rõ  r  s   &&&&r)   rù  Ú$ProcessRegistry._emit_watch_disabledi  s^   € à×Ñ×!Ñ!ð #
Ø×$Ñ$ WÓ-ð#
àÐ$Ø˜*ØØ6°w·z±z°lÀ%ÈÀuðCðDñ#
ö 	r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r&   r   r'   ©r!  r   )r(   rß   s   "€r)   r*   r°  v  s   ø€ ÷ 
ñ 
¡>ð 
±dñ 
r+   c                ó<  € R\         P                  ! 4       P                  RV P                  RV P                  RV P
                  RV P                  RV P                  RV P                  RV P                  /\         Uu/ uF  q\        V R	V 24      bK  	  upC# u upi )
zFSession identity + watcher routing fields shared by every watch event.Úevent_idrf  rw  r  ra  r<  r;  rì   r”  )r¦   r§   r¨   rf  rw  r`  ra  r<  r;  rì   Ú_WATCHER_ROUTE_KEYSÚgetattr)r   Úkeys   & r)   rÑ  Ú!ProcessRegistry._watch_event_baseu  sš   € ð œŸ
š
›×(Ñ(Ø˜'×,Ñ,Ø ×!:Ñ!:Ø˜'Ÿ*™*Ø˜7×.Ñ.Ø�w—‘Ø˜W×2Ñ2Ø�w—‘ð

õ CVÓVÑBU¸3”G˜G x°¨uÐ%5Ó6Ò6ÑBUÑVð

ð 
	
ùò Ws   Á=Bc                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r&   Útype_r  r'   r  )r(   rß   s   "€r)   r*   r°  …  s"   ø€ ÷ 
ñ 
¡3ð 
±ð 
Á$ñ 
r+   c                ó6   € RRRRRRRV /VCRVRRRRR	RR
RRR/C# )z/Unaddressed (all-sessions) watch breaker event.r  r9   ra  rì   rË  r  ÚplatformÚchat_idÚuser_idÚ	user_nameÚ	thread_idr/   )r  r  Úextras   &&,r)   Ú_global_watch_eventÚ#ProcessRegistry._global_watch_event„  sG   € ð ˜"˜m¨R°¸BÀÈð
ØQVð
à�wØ˜˜I r¨9°b¸+ÀrÈ;ÐXZñ
ð 	
r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r&   rÆ  r'   )rŒ  rs   )r(   rß   s   "€r)   r*   r°  �  s   ø€ ÷ (ñ (¡uð (±ñ (r+   c                ó¢  € . pV P                   ;_uu_ 4        V P                  '       dh   WP                  8¼  dX   V P                  pRV n        ^ V n        V^ uV n        V n        V^ 8”  d(   VP                  V P                  RRV R2VR7      4       V P                  '       d-   WP                  8  d   V ;P                  ^,          un        RpMÁWP                  ,
          \        8¼  d   V^ uV n        V n        V P                  \        8  pV'       d   V ;P                  ^,          un        MbV\        ,           V n        V ;P                  ^,          un        VP                  V P                  RR\         R	\         R
\         R24      4       RRR4       V F  pV P                  P                  V4       K   	  X#   + '       g   i     L6; i)a  True if this watch_match may pass the global breaker.
In cooldown: drop and count. Otherwise slide the rolling window; exceeding
the cap trips the breaker for WATCH_GLOBAL_COOLDOWN_SECONDS with ONE
"tripped" summary, and the cooldown's end emits ONE "released" summary.r3   Úwatch_overflow_releasedz%Watch-pattern notifications resumed. z1 match event(s) were suppressed during the flood.)rõ  FÚwatch_overflow_trippedzWatch-pattern overflow: >z notifications in zCs across all processes. Suppressing further watch_match events for ús.N)r£  r¥  r§  r¤  r¦  rN   r  ÚWATCH_GLOBAL_WINDOW_SECONDSÚWATCH_GLOBAL_MAX_PER_WINDOWÚWATCH_GLOBAL_COOLDOWN_SECONDSrž  rÓ  )r>  rÆ  Úeventsrõ  ÚadmitÚmsgs   &&    r)   rü  Ú#ProcessRegistry._global_watch_admit�  s¨  € ð
 ˆØ×$×$Ó$à×/×/Ð/°C×;[Ñ;[Ô4[Ø!×FÑF�
Ø36�Ô0Ø<=�Ô9ØRUÐWXÐO�Ô/°Ô1OØ ”>Ø—M‘M $×":Ñ":Ø1Ø?Ø%˜,Ð&WðYà#-ð	 #;ó #/ô 0ð
 ×/×/Ð/°C×:ZÑ:ZÔ4Zà×9Ò9¸QÕ>Õ9Ø‘à×8Ñ8Õ8Ô<WÔWØVYÐ[\ÐS�DÔ3°TÔ5SØ×6Ñ6Ô9TÑT�ßØ×2Ò2°aÕ7Ö2à7:Ô=ZÕ7Z�DÔ4Ø×=Ò=ÀÕBÕ=Ø—M‘M $×":Ñ":Ø0Ø3Ô4OÐ3Pð Q,Ü,GÐ+Hð IFä8Ð9¸ð=ó#>ô ?÷5 %ó@ ˆCØ×!Ñ!×%Ñ% cÖ*ñ àˆ÷E %×$ús   —BF>Â#A0F>ÄA<F>Æ>G	c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# ©r&   rb  r'   ©r   r6   rs   )r(   rß   s   "€r)   r*   r°  ¸  s   ø€ ÷  ñ  ¡©¥ð  ±$ñ  r+   c                ó2   € V '       g   R# ^ RI Hp V! V 4      # )z1Best-effort liveness check for host-visible PIDs.F)Ú_pid_exists)rÁ   r.  )rb  r.  s   & r)   Ú_is_host_pid_aliveÚ"ProcessRegistry._is_host_pid_alive·  s   € ÷ Ùõ 	/Ù˜3ÓÐr+   c                óF   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          /# r+  )r   r6   )r(   rß   s   "€r)   r*   r°  Â  s#   ø€ ÷ ñ ¡8©C¥=ð ±X¹cµ]ñ r+   c                óX   €  ^ RI Hp V '       d	   V! V 4      # R#   \         d     R# i ; i)z<Kernel start ticks for a host PID, or None when unavailable.)Úget_process_start_timeN)rÁ   r3  r±   )rb  r3  s   & r)   Ú_safe_host_start_timeÚ%ProcessRegistry._safe_host_start_timeÁ  s/   € ð	Ý=ß25Ñ)¨#Ó.Ð?¸4Ð?øÜô 	Úð	ús   ‚ � ˜ š)¨)c                óL   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          RS[/# ©r&   rb  Úexpected_startr'   r,  )r(   rß   s   "€r)   r*   r°  Ë  s0   ø€ ÷ Xñ X¡H©S¥Mð XÁ8ÉCÅ=ð XÑUYñ Xr+   c                ót   € V P                  V4      ;'       d!    VRJ ;'       g    V P                  V4      V8H  # )ac  True only if ``pid`` is alive AND still the process we spawned.
The kernel recycles PIDs, so a stored number can later name an unrelated
process (seen in the wild: a browser's session leader tree-killed). The kernel
start time captured at spawn must match the live one; with no baseline
(legacy checkpoints, no ``/proc``) degrade to a bare liveness check.N)r/  r4  )Úclsrb  r8  s   &&&r)   Ú_host_pid_is_oursÚ!ProcessRegistry._host_pid_is_oursÊ  sD   € ð ×%Ñ% cÓ*÷ Xð XØ˜dÐ"×VÐV c×&?Ñ&?ÀÓ&DÈÑ&Vð	Xr+   c                óL   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          RS[/# r7  )r   r6   rf   )r(   rß   s   "€r)   r*   r°  Ô  s+   ø€ ÷ ñ ¡x±¥}ð ÁhÉsÅmð ÑX[ñ r+   c                óÀ   € V P                  W4      '       d   R# V'       d   V P                  V4      '       g   R# Vf   R# V P                  V4      pVe   W28X  d   R# R# )uœ  How a recovered host PID should be supervised.

``running`` â€” alive and still ours (start time matches, no baseline, or
the start-time probe could not be read). Re-attach; do not invent an exit.
``reused`` â€” alive, and the start time positively differs. The number
belongs to someone else; close our entry and never signal that PID.
``gone`` â€” the PID is not alive. Prune it; no exit status was collected.
ÚrunningÚgoneÚreused)r;  r/  r4  )r>  rb  r8  Úcurrents   &&& r)   Ú_detached_host_fateÚ#ProcessRegistry._detached_host_fateÔ  sW   € ð ×!Ñ! #×6Ò6Ùß˜$×1Ñ1°#×6Ò6ÙØÒ!ÙØ×,Ñ,¨SÓ1ˆØŠ?˜gÔ7ÙÙr+   c                óF   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          /# r  )r   r!  )r(   rß   s   "€r)   r*   r°  è  s&   ø€ ÷ ñ ±¹.Õ1Ið ÉhÑWeÕNfñ r+   c                óP  € VeH   VP                   '       g6   VP                  '       d$   VP                  R8w  g   VP                  '       d   V# V P	                  VP
                  VP                  4      pVR8X  d   V# VR8X  d   V P                  V4      # V P                  V4       V# )z¢Re-attach, close, or prune a recovered host-PID session.

A completion is not queued here: recovery has no waitable handle, so it
never collected an exit status.
r6  r?  r@  )	r5  ri  rj  ro  rC  rb  rg  Ú_prune_uncollected_detachedÚ_close_reused_detached)r>  r   Úfates   && r)   Ú_refresh_detached_sessionÚ)ProcessRegistry._refresh_detached_sessionè  s�   € ð Š?˜gŸnŸn˜n°G×4D×4DÐ4DÈ×HYÑHYÐ]cÔHcÐgn×gy×gyÐgyØˆNØ×'Ñ'¨¯©°W×5LÑ5LÓMˆØ�9ÔØˆNØ�6Œ>Ø×3Ñ3°GÓ<Ð<Ø×#Ñ# GÔ,Øˆr+   c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r&   r   r'   N©r!  )r(   rß   s   "€r)   r*   r°  ø  s   ø€ ÷ (ñ (©nð (Àñ (r+   c                óH  € VP                   ;_uu_ 4        VP                  '       d    RRR4       R# RVn        RRR4       V P                   ;_uu_ 4        VP                  V P                  9   dA   \        P                  ! 4       Vn        V P                  P                  VP                  R4       WP                  VP                  &   RRR4       V P                  4        VP                  P                  4        R#   + '       g   i     LÌ; i  + '       g   i     LO; i)z·Close an entry whose PID was recycled onto another process.

The stranger is not signalled, and no completion is queued: we never
collected an exit status for the process we spawned.
NT)rF  r5  r`  r™  r‘   rh  rè   rš  Ú_write_checkpointr„  r   ©r>  r   s   &&r)   rH  Ú&ProcessRegistry._close_reused_detachedø  s´   € ð �]�]‹]Ø�~�~ˆ~Ø÷ ‰]ð "ˆGŒN÷ ð �Z�Z‹ZØ�z‰z˜TŸ]™]Ô*Ü$(§I¢I£K�Ô!Ø—‘×!Ñ! '§*¡*¨dÔ3Ø)0�N‰N˜7Ÿ:™:Ñ&÷	 ð
 	×ÑÔ Ø×!Ñ!×%Ñ%Ö'÷ �]ú÷ �Zús   •C>³C>ÁA4DÃ>D	ÄD!	c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# r  )r!  r   )r(   rß   s   "€r)   r*   r°  
  s    ø€ ÷ 9ñ 9±>ð 9ÁhÉ~ÕF^ñ 9r+   c                ó>  € VP                   ;_uu_ 4        RVn        RRR4       V P                   ;_uu_ 4        V P                  P                  VP                  R4       VP
                  '       d   WP                  VP                  &   M&V P                  P                  VP                  R4       RRR4       V P                  4        VP                  P                  4        VP
                  '       d   V# R#   + '       g   i     Lä; i  + '       g   i     Lc; i)zÓDrop a recovered entry whose PID is gone, without inventing an exit.

An owned systemd scope stays reachable so kill can still reap it. A
scope-less entry is removed: poll/list must not report a collected exit.
TN)
rF  r5  r™  rè   r`  rk  rš  rP  r„  r   rQ  s   &&r)   rG  Ú+ProcessRegistry._prune_uncollected_detached
  s·   € ð �]�]‹]Ø!ˆGŒN÷ à�Z�Z‹ZØ�M‰M×Ñ˜gŸj™j¨$Ô/Ø×#×#Ð#Ø-4—‘˜wŸz™zÒ*à—‘×"Ñ" 7§:¡:¨tÔ4÷ ð 	×ÑÔ Ø×!Ñ!×%Ñ%Ô'Ø!×.×.Ð.ˆwÐ8°DÐ8÷ �]úç�Zús   •C9¹A8DÃ9D		ÄD	c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# r  )r   r!  rs   )r(   rß   s   "€r)   r*   r°    s    ø€ ÷ :ñ :©±.Õ)Að :Ádñ :r+   c                ó  € \        VRJ;'       dv    VP                  ;'       db    VP                  RJ ;'       dL    VP                  ;'       d8    VP                  R8H  ;'       d!    V P                  VP                  4      '       * 4      # )z�True when a detached entry was closed without a collected exit status
and the PID is no longer alive. List/poll must not report that as exited.Nr6  )rs   r5  r[  ri  rj  r/  rb  rQ  s   &&r)   Ú_uncollected_goneÚ!ProcessRegistry._uncollected_gone  sŠ   € ô Ø˜4Ð÷ 9ð 9 G§N¡N÷ 9ð 9°w×7HÑ7HÈDÐ7P÷ 9ð 9Ø× Ñ ÷9ð 9Ø%,×%6Ñ%6¸&Ñ%@÷9ð 9à×+Ñ+¨G¯K©KÓ8Ô8ó:ð 	:r+   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r&   Úsectionr  rÔ   )r(   rß   s   "€r)   r*   r°  %  s   ø€ ÷ Dñ D™sð D©ñ Dr+   c                ó\   € ^ RI HpHpHp V! V! 4       W4      pVf   W0,          V,          # T# )zÏ``config.yaml`` value for ``section.key``, else the DEFAULT_CONFIG value.
Raises if config is unreadable; callers wrap with their own hard fallback so
registry code paths never crash on a broken config file.)ÚDEFAULT_CONFIGÚcfg_getÚread_raw_config)Úhermes_cli.configr]  r^  r_  )r[  r  Úfallbackr]  r^  r_  Úvals   &&&    r)   Ú_config_valueÚProcessRegistry._config_value$  s1   € ÷
 	OÑNá‘oÓ'¨Ó6ˆØ/2ª{ˆ~Õ& sÕ+ÐCÀÐCr+   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r&   r  ra  r'   )rf   rŒ  )r(   rß   s   "€r)   r*   r°  /  s"   ø€ ÷ ñ ™Sð ©Eð ±eñ r+   c           	     ó|   €  \        \        \        P                  RW4      4      R4      #   \         d    Tu # i ; i)zR``terminal.<key>`` as a non-negative float (0 disables); *fallback* if unreadable.Úterminalr3   )rS   rŒ  r—  rc  r±   )r  ra  s   &&r)   Ú_config_secondsÚProcessRegistry._config_seconds.  s;   € ð	Ü”uœ_×:Ñ:¸:ÀsÓUÓVÐX[Ó\Ð\øÜô 	ØŠOð	ús   ‚(+ «;º;c                ó    <€ V ^8„  d   QhRS[ /# r%   ©rŒ  )r(   rß   s   "€r)   r*   r°  7  s   ø€ ÷ Qñ Q©ñ Qr+   c                 ó.   € \         P                  RR4      # )zGGrace (s) between SIGTERM and escalated SIGKILL; 0 disables escalation.Údaemon_term_grace_secondsg       @©r—  rh  r/   r+   r)   Ú_daemon_term_grace_secondsÚ*ProcessRegistry._daemon_term_grace_seconds6  s   € ô ×.Ñ.Ð/JÈCÓPÐPr+   c                ó    <€ V ^8„  d   QhRS[ /# r%   rN  )r(   rß   s   "€r)   r*   r°  >  s   ø€ ÷ -ñ -ÑTbñ -r+   c                óÜ   € ^ RI Hp \        RRR\        P                  ! 4       P
                  R,           2RV RVRVRVR	VR
V! RR4      R\        V 4      R\        P                  ! 4       /	VB # )r  )Úget_session_envr`  Úproc_:Né   Nrì   r<  r;  ra  re  rw  ÚHERMES_SESSION_IDr9   rl  rf  r/   )Úgateway.session_contextrs  r!  r¦   r§   r¨   r"   r‘   )rì   r<  r;  ra  re  r  rs  s   &&&&&, r)   Ú_new_sessionÚProcessRegistry._new_session=  s–   € å;äñ -Ø”t—z’z“|×'Ñ'¨Õ,Ð-Ð.ð-Ø8?ð-ØIPð-à'ð-à5@ð-àFIð-ñ .Ð.AÀ2ÓFð-ô /¨wÓ7ð	-ô
 —y’y“{ð-ð
 ',ñ-ð 	-r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r&   rˆ   r'   )r   rf   )r(   rß   s   "€r)   r*   r°  I  s   ø€ ÷ 
%ñ 
%™3ð 
%¡3ñ 
%r+   c                ód  € \        V RR4      p\        V4      '       dQ    V! 4       p\        V\        4      '       d3   VP	                  R4      '       d   VP                  R4      ;'       g    R# \        P                  ! 4       #   \         d!   p\        P                  RT4        Rp?L;Rp?ii ; i)zEReturn the writable sandbox temp dir for env-backed background tasks.Úget_temp_dirNr<   z*Could not resolve environment temp dir: %s)r  ÚcallableÚ
isinstancerf   rJ   r÷  r±   rF   r¯   ÚtempfileÚ
gettempdir)rˆ   r|  Útemp_dirr·   s   &   r)   Ú_env_temp_dirÚProcessRegistry._env_temp_dirH  s•   € ô ˜s N°DÓ9ˆÜ�L×!Ò!ðPÙ'›>�Ü˜h¬×,Ò,°×1DÑ1DÀS×1IÒ1IØ#Ÿ?™?¨3Ó/×6Ð6°3Ð6ô ×"Ò"Ó$Ð$øô ô PÜ—‘ÐIÈ3×OÑOûðPús#    3B ÁB Á,B ÂB/ÂB*Â*B/c                óH   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[S[,          /# )r&   r   Úsafe_commandrÅ   Úlabelr'   )r!  rf   rg   )r(   rß   s   "€r)   r*   r°  U  s9   ø€ ÷ ñ ¡>ð Áð ÑSVð Ñ_bð ÑgkÑloÕgpñ r+   c                óð   € \        4       RRV 2.p\        ;'       d    \        4       pV'       d(   \        4       '       d   RV R2Vn        \        WSR7      # V'       d   \        P                  RV4       V# )a  Login-shell argv for *safe_command* (parity with LocalEnvironment: rc files
sourced, user tools on PATH), wrapped in a transient systemd scope when we are
the supervised gateway (own cgroup: an OOM kills only the worker, not the
gateway and its messaging control plane).z-liczset +m; rÇ   z.scoperø   zz%s background executor not isolated in a systemd scope (systemd-run --user unavailable); worker shares the gateway cgroup.)r   r…   rÂ   r¸   rk  rÈ   rF   r¯   )r>  r   r…  rÅ   r†  re   Úin_supervised_gateways   &&&&&  r)   Ú_scope_argvÚProcessRegistry._scope_argvU  su   € ô
 “˜v¨°,°Ð'@ÐAˆä )× NÐ NÔ.LÓ.NÐß Ô%F×%HÒ%HØ%3°K°=ÀÐ#GˆGÔ Ü,¨TÔKÐKß ô �L‰LðVØW\ô^ð ˆr+   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r&   Úenv_varsr'   r*  )r(   rß   s   "€r)   r*   r°  i  s   ø€ ÷ ñ ™Tð ¡dñ r+   c                óP   € ^ RI Hp \        \        V! 4       V 4      4      pRVR&   V# )z`Sanitized child env from the session's client toolchain; PYTHONUNBUFFERED so poll sees progress.)Útoolchain_environr¼   ÚPYTHONUNBUFFERED)Úagent.session_client_envrŽ  r
   r	   )rŒ  rŽ  rˆ   s   &  r)   Ú
_spawn_envÚProcessRegistry._spawn_envh  s-   € õ 	?ÜÔ4Ñ5FÓ5HÈ(ÓSÓTˆØ"%ˆÐÑØˆ
r+   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r&   r   Úreader_namer'   Nrå  )r(   rß   s   "€r)   r*   r°  p  s$   ø€ ÷ !ñ !¡nð !ÑRUð !Ðimñ !r+   c                óh  € ^ RI Hp \        P                  ! V! 4       P                  W!.VO5RVR7      pWan        V P                  ;_uu_ 4        V P                  4        VP                  4        WP                  VP                  &   RRR4       V P                  4        R#   + '       g   i     L"; i)zLRegister before the reader can publish completion, even for an exited child.)Úcopy_contextT)r¹  Úargsr»  rº  N)Úcontextvarsr–  r�  r�  r«   r‡  rF  Ú_prune_if_neededr¾  r™  r`  rP  )r>  r   Úreader_targetr”  Ú
extra_argsr–  Úreaders   &&&&&  r)   Ú_track_startedÚProcessRegistry._track_startedp  sƒ   € å,ô ×!Ò!©«×);Ñ);À=ÐBgÐ\fÑBgØ)-°KôAˆà!'ÔØ�Z�Z‹ZØ×!Ñ!Ô#ð �L‰LŒNØ(/�M‰M˜'Ÿ*™*Ñ%÷ ð 	×ÑÖ ÷ �Zús   Á9B!Â!B1	c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[ /# )r&   r   r…  rŒ  r'   ©r!  rf   r   )r(   rß   s   "€r)   r*   r°  €  s+   ø€ ÷ ñ ©ð Ácð ÑUYð Ñ^lñ r+   c                ó  € \         '       d   ^ RIHp M^ RIHp V P	                  WVP
                  R4      pV P                  V4      pVP                  '       d   \        V4      pVP                  RR4       VP                  RR4       VP                  WQP                  VRR7      pVP                  Vn        V P                  VP                  4      Vn        Wqn        V P!                  WP"                  RVP
                   24       V# )	zÌPTY spawn for interactive CLI tools (Codex, Claude Code, REPLs).
Raises ImportError when no PTY backend is installed and re-raises any spawn
failure; ``spawn_local`` falls back to pipe mode in both cases.)Ú
PtyProcessÚPTYÚ	GIT_PAGERÚcatÚPAGER)re  rˆ   Ú
dimensionszproc-pty-reader-)é   éx   )Ú_IS_WINDOWSÚwinptyr¢  Ú
ptyprocessr‰  r`  r‘  rk  r�   Ú
setdefaultÚspawnre  rb  r4  rg  rŠ  r�  Ú_pty_reader_loop)r>  r   r…  rŒ  Ú_PtyProcessClsÚpty_argvÚpty_envÚpty_procs   &&&&    r)   Ú_spawn_local_ptyÚ ProcessRegistry._spawn_local_pty€  s×   € ÷ ‹;Þ;å?Ø×#Ñ# G¸7¿:¹:ÀuÓMˆØ—/‘/ (Ó+ˆØ××ÐÜ*¨7Ó3ˆGð 	×Ñ˜;¨Ô.Ø×Ñ˜7 EÔ*Ø!×'Ñ'¨·k±kÀwÐ[dÐ'ÓeˆØ—l‘lˆŒØ"&×"<Ñ"<¸W¿[¹[Ó"IˆÔØŒØ×Ñ˜G×%:Ñ%:Ð>NÈwÏzÉzÈlÐ<[Ô\Øˆr+   Nr9   c                ól   <€ V ^8„  d   QhRS[ RS[ R,          RS[ RS[ RS[R,          RS[RS[ R	S[R
S[/	# )r&   rì   re  Nr<  ra  rŒ  Úuse_ptyr;  rn  r'   )rf   r   rs   r!  )r(   rß   s   "€r)   r*   r°  —  sl   ø€ ÷ Añ AÙðAÙ!$ t¥ðAÙ=@ðAÙTWðAá˜•+ðAá/3ðAáLOðAñ !ðAñ .<ñAr+   c	                ó  € ^ RI Hp	 V	! V4      p
T P                  YYt\        T;'       g    \        P
                  ! 4       4      VR7      pRp\        VP                  4      pV'       d   Vf    V P                  WºV4      # \         '       d   R
\#        4       /M/ pV'       d   VP                   R2MVP                  pT P%                  Y½'       d   \'        WÚ4      MT
VR4      pV P)                  V4      pVP                  '       d   \+        V4      pV'       d   \-        V4      M\.        P0                  p \.        P2                  ! V3RRRVP4                  RVRRRRRVR\.        P6                  R\.        P8                  RR/	VB pV'       d   \        P:                  ! V4       T\=        T;'       g    R	4      uTn        Tn         TPB                  Tn!        T PE                  TPB                  4      Tn#         T PI                  Y½'       d   T PJ                  MT PL                  RTP                   24       T#   \         d    \        P                  R4        ELØ\         dd   p\        P                  RT4       TP                  '       d1   Rp\        TP                  4      '       g   \        R4      ThR	Tn         Rp?EL@Rp?ii ; i  T'       d   \        P:                  ! T4       i i ; i  \         d    T PO                  TT4       h i ; i)aA  Spawn a background process locally (TERMINAL_ENV=local; other backends use
spawn_via_env()). ``use_pty`` requests a pseudo-terminal via ptyprocess/pywinpty
for interactive CLIs, falling back to a plain pipe when unavailable or failing.
``persist_on_release`` keeps the process out of agent-lifecycle kill sweeps (#41225).)Ú_rewrite_compound_background)rn  FNz3ptyprocess not installed, falling back to pipe modez0PTY spawn failed (%s), falling back to pipe modeTzZPTY scope could not be reaped; refusing pipe fallback to avoid duplicate command executionr9   Úcreationflagsz-pipe-fallbackÚLocalrC  re  rˆ   r;   r:   r   r¡   Ústdoutr®   r�   Ústart_new_sessionúproc-reader-)(Útools.terminal_tool_sudor¹  rx  r   rA   Úgetcwdr   r`  r´  ÚImportErrorrF   rG   r±   rk  r	  ÚRuntimeErrorrª  r   r‰  r   r‘  r�   r   rª   ÚPIPEr‹  re  ÚSTDOUTr¬   Úcloserf   rc  ro  rb  r4  rg  r�  Ú_log_reader_loopÚ_reader_loopÚ_reap_untracked)r>  rì   re  r<  ra  rŒ  r·  r;  rn  Ú_rewrite_bgr…  r   Úpty_scope_attemptedÚlogÚeÚ_popen_kwargsrÅ   Ú
spawn_argvrå   r,  Úprocs   &&&&&&&&&            r)   Úspawn_localÚProcessRegistry.spawn_local—  sÏ  € õ 	Yá" 7Ó+ˆØ×#Ñ# G°mÔRcÐdg×dvÐdvÔkm×ktÒktÓkvÓRwØ7Ið $ó Kˆà#Ðä §
¡
Ó+ˆß�s’{ð.Ø×,Ñ,¨WÀHÓMÐM÷ DOÃ;˜Ô*<Ó*>Ñ?ÐTVˆß7J˜Ÿ™˜ NÑ3ÐPW×PZÑPZˆØ×%Ñ% gÖY\Ô/BÀ3Ô/UÐbnØ&1°7ó<ˆ
à—O‘O HÓ-ˆ	Ø××ÐÜ,¨YÓ7ˆI÷ *-” Ô%´*·/±/ˆð	!Ü×#Ò#Øñ9Ø!%ð9Ø+2¯;©;ð9Ø<Eð9ØPWð9à ð9à)/ð9ä8B×8IÑ8Ið9äQ[×QcÑQcð9ð #'ð9ð +8ñ9ˆD÷
 Ü—’˜Ô Ø.2´C¸¿	¸	¸r³NÐ+ˆŒ˜Ô+Ø—h‘hˆŒØ"&×"<Ñ"<¸W¿[¹[Ó"IˆÔð	Ø×Ñ Æ#¨×)>Ò)>È4×K\ÑK\Ð`lÐmt×mwÑmwÐlxÐ^yÔzð ˆøôU ô VÜ—‘ÐT×UÜô 	.Ü—‘ÐQÐSTÔUØ×'×'Ð'Ø*.Ð'Ü-¨g×.BÑ.B×CÒCÜ*ðCóð  !ð!ð ,.�GÔ(ÿùð	.û÷< Ü—’˜Õ ð ûô ô 	Ø× Ñ  ¨$Ô/Øð	ús>   Á.H5 Ä5AK Ç6=K, È5 KÉKÉ!KÉ"AK Ë KË!K)Ë,Lc                ó>   <€ V ^8„  d   QhRS[ RS[P                  RR/# )r&   r   rÏ  r'   N)r!  rª   r‹  )r(   rß   s   "€r)   r*   r°  Ú  s)   ø€ ÷ !ñ !¡~ð !¹Z×=MÑ=Mð !ÐRVñ !r+   c                ó’  € \        \        4      ;_uu_ 4        VP                  '       d   \        VP                  4       V P	                  VP
                  VP                  4       RRR4       \        \        4      ;_uu_ 4        VP                  ^R7       RRR4       R#   + '       g   i     LD; i  + '       g   i     R# ; i)znPost-Popen setup failed: kill the orphaned subprocess (and any setsid
descendants) so nothing leaks untracked.N©rŸ   )r   r±   rk  r	  Ú_terminate_host_pidrb  rg  Úwait)r>  r   rÏ  s   &&&r)   rÈ  ÚProcessRegistry._reap_untrackedÚ  s„   € ô ”i× Õ Ø×#×#Ð#ô # 7×#7Ñ#7Ô8ð ×$Ñ$ T§X¡X¨w×/FÑ/FÔG÷ !ô ”i× Õ Ø�I‰I˜aˆIÔ ÷ !Ñ ÷ !× ú÷ !× Ð ús   ˜AB"ÂB5Â"B2	Â5C	r<  ra  r;  Úoutput_so_farrx  Tc                ót   <€ V ^8„  d   QhRS[ P                  RS[RS[S[,          RS[RS[RS[RS[RS[R	S[/	# )
r&   rÏ  rì   re  r<  ra  r;  rØ  rx  r'   )rª   r‹  rf   r   rs   r!  )r(   rß   s   "€r)   r*   r°  é  sc   ø€ ÷ ñ Ù×$Ñ$ðÙ25ðÙ<DÁS½MðÙTWðáðá.1ðáGJðñ !ðñ -;ñr+   c               ó*  € V P                  W$WeV4      p	Wn        VP                  V	n        V P                  V	P                  4      V	n        W‰n        V'       d   V	P                  V4       V P                  W�P                  RV	P                   24       V	# )aR  Take over a still-running foreground Popen as a tracked background session
(yield-to-background: the user sent a message while the command was running).
The caller has stopped its own drain thread; the registry's reader continues from
the pipe's current position and ``output_so_far`` seeds the buffer so nothing
already captured is lost.r¾  )
rx  rc  rb  r4  rg  rx  rI  r�  rÇ  r`  )
r>  rÏ  rì   re  r<  ra  r;  rØ  rx  r   s
   &&$$$$$$$ r)   Úadopt_localÚProcessRegistry.adopt_localé  s}   € ð ×#Ñ# G°mÐRUÓVˆØŒØ—h‘hˆŒØ"&×"<Ñ"<¸W¿[¹[Ó"IˆÔØ%7Ô"ßØ×!Ñ! -Ô0Ø×Ñ˜G×%6Ñ%6¸,ÀwÇzÁzÀlÐ8SÔTØˆr+   c                ó^   <€ V ^8„  d   QhRS[ RS[RS[R,          RS[RS[RS[RS[R	S[R
S[/	# )r&   rˆ   rì   re  Nr<  ra  rŸ   r;  rn  r'   )r   rf   r6   rs   r!  )r(   rß   s   "€r)   r*   r°  ü  sY   ø€ ÷ ñ ÙðÙ!$ðÙ+.°­:ðÙGJðÙ^aðáðá*-ðáHLðáYgñr+   c	                óÊ  aa€ V P                  W$WuW1RVR7      oV P                  V4      oVV3R lR 4       w  ršp\        P                  pRV! S4       RV! V4       RV! V	4       RV! V4       RV! V
4       R	V! V
4       2pTP	                  YÓ;'       g    R
VRR7      pVP                  RR
4      P                  4       p\        R \        \        P                  VP                  4       4       4       R4      Sn        SP                  f+   \        RVP                  R4       RT;'       g    R 24      hV P                  SV P                  RSP                   2WW«34       S# )aQ  Spawn a background process inside a non-local backend's sandbox.
The command is wrapped to capture its in-sandbox PID and redirect output to a
log file that later execute() calls poll. No live pipe or stdin, but it runs in
the correct sandbox context. ``persist_on_release`` keeps the process out of
agent-lifecycle kill sweeps (#41225).Úsandbox)rd  rj  rn  c              3   óL   <"  € T F  pS R SP                    RV 2x € K  	  R# 5i)z/hermes_bg_Ú.N©r`  )r  Úextr   r�  s   & €€r)   r  Ú0ProcessRegistry.spawn_via_env.<locals>.<genexpr>  s)   øé € Ð(vÑ_uÐX[¨H¨:°[ÀÇÁÀÈAÈcÈUÕ)SÓ_uùs   ƒ!$z	mkdir -p z && ( nohup bash -lc z > z$ 2>&1; rc=$?; printf '%s\n' "$rc" > z ) & echo $! > z && cat r9   F)re  rŸ   Úrewrite_compound_backgroundr,  c              3   óf   "  € T F'  qP                  4       '       g   K  \        V4      x € K)  	  R # 5ir  )rM   r6   )r  Úlns   & r)   r  rä    s#   é € ÐbÑ.Q¨×U_ÑU_×UaœGœC ŸG˜GÓ.Qùs   ‚1ž1Nzlaunch wrapper exited r­   z without a PID: z(no output)zproc-poller-)rË  rb  Úexit)rx  r‚  ÚshlexÚquoteÚexecuter†   rC   rö  Úmaprf   rI   rb  rÂ  r�  Ú_env_poller_loopr`  )r>  rˆ   rì   re  r<  ra  rŸ   r;  rn  Úlog_pathÚpid_pathÚ	exit_pathÚqÚ
bg_commandr¶   r,  r   r�  s   &&&&&&&&&       @@r)   Úspawn_via_envÚProcessRegistry.spawn_via_envü  sw  ù€ ð ×#Ñ# G°mÐRUÐnwØ7Ið $ó Kˆà×%Ñ% cÓ*ˆÝ(vÑ_uÓ(vÑ%ˆ˜IÜ�K‰Kˆà™˜(›�}ð % Ù ! '£
˜|¨3©q°«{¨mð </Ù/0°«|¨nð =Ù˜8›˜ X©a°«k¨]ð<ð 	ð
 —‘˜Z¯Y¨Y°BÀÐej�ÓkˆØ—‘˜H bÓ)×/Ñ/Ó1ˆÜÑb¬c´#·)±)¸V×=NÑ=NÓ=PÔ.QÓbÐdhÓiˆŒð �;‰;ÒÜÐ!7¸¿
¹
À<Ó8PÐ7QÐQaØ"(×"9Ð"9¨MÐ!:ð <ó =ð =à×ÑØ�T×*Ñ*¨l¸7¿:¹:¸,Ð,GÈ#ÐYaÐImô	oàˆr+   c                ó    <€ V ^8„  d   QhRS[ /# ©r&   r   rN  )r(   rß   s   "€r)   r*   r°    s   ø€ ÷ XJñ XJ¡Nñ XJr+   c                ó²  a aaaaa€ Ro\         P                  ! R4      ! RR7      oR VV V3R llpRp SP                  pVe   VP                  fF    Ve   VP	                  4        S P                  SSVRSP                  P                  V3R	 l4       R# VP                  o\        \        SR
R4      RR4      oVVV3R lp Se   \        '       g   SP                  4       MRp\        V\        4      '       d   V^ 8¼  g   Rp^ RIHp Ve	   V! V4      MRpVRJSn        ^ p^ p	 Ve„   SP                   P#                  4       '       d   ^ MRp
VP                  V
4      pV'       gG   SP                   P#                  4       '       d   MƒVP%                  4       e
   V^,          pV^8¼  d   M`Kˆ  V! 4       pVf   MRV'       d	   V! V4       SP                   P#                  4       '       d   V	\'        V4      ,          p	V	\(        8¼  d   M^ pKæ  Ve   VP	                  4        S P                  SSVRSP                  P                  V3R	 l4       R#   \         d    Rp ELzi ; i  \         d!   p\*        P-                  RT4        Rp?L~Rp?ii ; i  Te   TP	                  4        S P                  SSTRSP                  P                  T3R	 l4       i ; i)ar  Background thread: read stdout from a local Popen process.
``buffer.read1(4096)`` not ``TextIOWrapper.read(4096)``: on pipes the latter
blocks until EOF, landing "live" output in one burst at exit. Orphaned-pipe
guard: a backgrounded grandchild (``node server.js &``) inherits our pipe's write
end so EOF never arrives while it lives, which would park this thread and never
fire ``notify_on_complete``; on POSIX we wait on an ``fd_wait`` selector (no FD_SETSIZE
cap, #94928) and stop draining shortly after the direct child exits.
Windows pipes lack select(), so the lazy ``_reconcile_local_exit`` is the net (#68915, #8340).
Tr:   r¡   rÿ   c                ó$   € V ^8„  d   QhR\         /# )r&   rä  rÔ   )r(   s   "r)   r*   Ú2ProcessRegistry._reader_loop.<locals>.__annotate__.  s   € ÷ 	0ñ 	0¤ñ 	0r+   c                 óˆ   <€ S'       d'   SP                  V 4      p V P                  4       '       * oSP                  SV 4       R # r  )rá  rC   Ú_ingest_output)rä  Ú
head_noiser>  r   s   &€€€r)   Ú_append_chunkÚ3ProcessRegistry._reader_loop.<locals>._append_chunk.  s4   ø€ çØ×/Ñ/°Ó6�Ø!&§¡£Ô.�
Ø×Ñ ¨Ö/r+   NÚProcessc                  ó0   <€ S P                   P                  # r  )rc  r­   ©r   s   €r)   Ú<lambda>Ú.ProcessRegistry._reader_loop.<locals>.<lambda>t  s   ø€ ¨g¯o©o×.HÒ.Hr+   ÚbufferÚread1c                 óˆ   <€ Sf   SP                  R4      ;'       g    R# S! R4      p V '       d   SP                  V 4      # R# )zLOne 4 KiB read: decoded text ('' for a partial multibyte tail), None at EOF.Né   )Úreadr°   )ÚrawÚdecoderÚraw_readr¼  s    €€€r)   Ú
_read_onceÚ0ProcessRegistry._reader_loop.<locals>._read_once<  s?   ø€ àÒ#Ø!Ÿ;™; tÓ,×4Ð4°Ð4Ù˜t“n�ß.1�w—~‘~ cÓ*Ð;°tÐ;r+   )Úopen_fd_waitergš™™™™™É?zProcess stdout reader ended: %s)ÚcodecsÚgetincrementaldecoderrc  r¼  rÅ  Ú_finish_readerrÖ  r  rª  Úfilenor±   r~  r6   Útools.environments.fd_waitr  r‰  rˆ  Úis_setÚpollr0  Ú_FINAL_DRAIN_MAX_CHARSrF   r¯   )r>  r   rý  Ú_waiterrÏ  r  Úfdr  Úidle_after_exitÚdrained_after_requestÚwait_sÚreadyrä  rÌ  r
  rü  r  r¼  s   ff            @@@@r)   rÇ  ÚProcessRegistry._reader_loop  sŠ  ý€ ð ˆ
ô ×.Ò.¨wÔ7¸yÔIˆ÷	0ò 	0ð ˆð?	JØ—?‘?ˆDØŠ|˜tŸ{™{Ò2Øðp Ò"Ø—‘”Ø×ÑØ˜ -°Ø—‘×$Ñ$Ô&HöJðs —[‘[ˆFÜœw v¨x¸Ó>ÀÈÓNˆH÷<ðØ(0Ò(<Ç[Ã[�V—]‘]”_ÐVZ�ô ˜r¤3×'Ò'¨B°!¬GØ�ÝAØ,.ªN‘n RÔ(ÀˆGØ)0¸Ð)<ˆGÔ&ØˆOØ$%Ð!ØØÒ&ð #*×"BÑ"B×"IÑ"I×"KÒ"K™QÐQT�FØ#ŸL™L¨Ó0�Eß Ø"×;Ñ;×BÑB×DÒDØ!ð  Ÿ9™9›;Ò2à+¨qÕ0˜OØ*¨aÔ/Ø!Ù Ù"›�Ø’=ØßÙ! %Ô(Ø×3Ñ3×:Ñ:×<Ò<ð *¬S°«ZÕ7Ð)Ø,Ô0FÔFØØ"#’ð Ò"Ø—‘”Ø×ÑØ˜ -°Ø—‘×$Ñ$Ô&HöJøôY ô Ø“ðûôN ô 	?Ü�L‰LÐ:¸A×>Ñ>ûð	?ûð Ò"Ø—‘”Ø×ÑØ˜ -°Ø—‘×$Ñ$Ô&HõJús£   ´I$ Â,I$ ÃI ÃI Ã&A$I$ ÅI$ Å(I$ ÆJ Æ	"I$ Æ+J Æ,I$ Æ9J Æ:I$ Ç'I$ Ç*I$ ÈJ ÈI$ ÉI!ÉI$ É I!É!I$ É$JÉ/J
ÊJ Ê
JÊJ ÊAKc                ó   <€ V ^8„  d   QhRR/# r·  r/   )r(   rß   s   "€r)   r*   r°  v  s   ø€ ÷ 2ñ 2ÐRVñ 2r+   c                ó”  € \        \        4      ;_uu_ 4        VP                  RRR7      pV'       d	   V! V4       RRR4        V! 4        V P                  W! 4       4       R#   + '       g   i     L0; i  \         dF   pT! 4       f   \        P	                  RYH4        Rp?R# \        P	                  RYH4        Rp?LvRp?ii ; i)az  Reader-thread teardown: flush the decoder (a truncated multibyte tail becomes
one U+FFFD instead of vanishing), reap the child (no zombies), record the exit.

A process may close stdout long before it exits.  The reader owns a dedicated
daemon thread, so it must keep waiting rather than publish a false completion
and discard the only ``Popen`` handle that can reap the child.
r+   T)ÚfinalNz+%s wait failed; leaving process tracked: %sz/%s wait failed; recording known exit status: %s)r   r±   r°   rF   rG   Ú_finish_exited)	r>  r   r
  rN   r†  rÖ  r[  ÚtailrÌ  s	   &&&&&&&  r)   r  ÚProcessRegistry._finish_readerv  s™   € ô ”i× Õ Ø—>‘> #¨T�>Ó2ˆDßÙ�t”÷ !ð	XÙŒFð 	×Ñ˜G Y£[Ö1÷ !× ûô ô 	Xñ ‹{Ò"Ü—‘ÐLÈeÔWÝÜ�N‰NÐLÈe×WÑWûð	Xús)   ˜$A$ÁA7 Á$A4	Á7CÂCÂ'CÃCc          
      ó8   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[/# )r&   r   rˆ   rî  rï  rð  )r!  r   rf   )r(   rß   s   "€r)   r*   r°  �  s2   ø€ ÷ :ñ :©ð :¹Sð :ÉCð :Ñ[^ð :Ñknñ :r+   c                ój  € \         P                  p^ pVP                  '       EgŽ   \        P                  ! ^4        VP                  V P                  V! V4      V4      ^
R7      P                  RR4      pVP                  R4      w  ršp V	P                  4       w  rÍ\        V4      p\        V4      pVeJ   W÷8  dB   VP                  ;_uu_ 4        VP                  '       d    RRR4       R# RVn        RRR4       TpV'       d¹   VP                  ;_uu_ 4        VP                  '       d    RRR4       R# V;P                  V,          un        \        VP                  4      VP                  8”  d    VP                  VP                  ) R Vn        RRR4       V P!                  W4       V P#                  W4       VP                  RV! V4       R2^R7      pVP                  RR4      P%                  4       pV'       d¬   VP'                  4       R,          P%                  4       R8w  d   VP                  R	V! V4       R
2^R7      P                  RR4      P%                  4       p \        VP'                  4       R,          P%                  4       4      pV P+                  VV4       R# EK�  EK   R#   \         d    RpRpRp ELi ; i  + '       g   i     ELà; i  + '       g   i     ELT; i  \        \(        3 d    Rp Lqi ; i  \,         d    T P+                  TRRRR7        R# i ; i)zBBackground thread: poll a sandbox log file for non-local backends.rÔ  r,  r9   rÙ  Nzkill -0 "$(cat z# 2>/dev/null)" 2>/dev/null; echo $?Ú0zcat ú 2>/dev/nullÚlostÚbackend_lost)rV  rW  r?   )ré  rê  r5  r‘   rÂ  rë  Ú_log_delta_commandr†   rK   rÞ  r6   rD   rF  r'  r0  rS  r  rè  rC   rI   Ú
IndexErrorr!  r±   )r>  r   rˆ   rî  rï  rð  rñ  Úprev_output_bytesr	  Úheaderrÿ  rÔ  Úsize_strÚ
offset_strÚnew_sizeÚused_offsetr    Úcheck_outputÚexit_strr[  s   &&&&&&              r)   rí  Ú ProcessRegistry._env_poller_loop�  sÊ  € ä�K‰KˆàÐØ—.—.‘.Ü�JŠJ�qŒMð3à—k‘k $×"9Ñ"9¹!¸H»+ÐGXÓ"YØ*,ð "ó .ß.1©c°(¸BÓ.?ð à#&§=¡=°Ó#6Ñ �˜5ð	Ø+1¯<©<«>Ñ(�HÜ" 8›}�HÜ"% j£/�Kð Ò'Ø"Ô6à$Ÿ]Ÿ]›]Ø&Ÿ~Ÿ~˜~Ø &÷ +™]ð 57˜GÔ1÷ +ð )1Ð%ßð !ŸŸ›Ø"Ÿ>Ÿ>˜>Ø"÷ '™ð  ×-Ò-°Õ6Õ-Ü˜w×4Ñ4Ó5¸×8PÑ8PÔPØ4;×4IÑ4IÈ7×KcÑKcÐJcÐJdÐ4e˜GÔ1÷ 'ð ×.Ñ.¨wÔ>Ø×%Ñ% gÔ5àŸ™Ø&¡q¨£{ mÐ3WÐXÐbcð $ó e�à$Ÿy™y¨°2Ó6×<Ñ<Ó>�ß L×$;Ñ$;Ó$=¸bÕ$A×$GÑ$GÓ$IÈSÔ$Pà"Ÿ{™{¨T±!°I³,°¸|Ð+LÐVW˜{ÓX×\Ñ\Ð]eÐgiÓj×pÑpÓr�Hð'Ü$'¨×(;Ñ(;Ó(=¸bÕ(A×(GÑ(GÓ(IÓ$J˜	ð ×'Ñ'¨°Ô;Ùò %Q’<ñQ !øô "ô ð  $�HØ"&�KØ“Eðú÷ +Ÿ]˜]ú÷ 'Ÿ˜ûô" '¬
Ð3ô 'Ø$&š	ð'ûô ô ð ×#Ñ# G¨R¸À~Ð#ÔVÚð	ús±   ½AL Â(J5 Â3L ÃKÃ%L Ã/KÃ6L ÄL ÄK!Ä0L Ä:AK!ÆA.L ÈA%L É+.K5 ÊL Ê5K
ËL Ë	K
Ë
L ËK	Ë	L Ë!K2	Ë,	L Ë5LÌL Ì
LÌL Ì L2Ì1L2c                ó    <€ V ^8„  d   QhRS[ /# rö  rN  )r(   rß   s   "€r)   r*   r°  Ë  s   ø€ ÷ 4Tñ 4T©ñ 4Tr+   c           	     óš  a aa€ SP                   o\        P                  ! R4      ! RR7      pRp\        '       g   ^ RIHp V! ^^xR7      pR V V3R llp SP                  4       '       d¡    SP                  R	4      pV'       d…   VeD   \        V\        4      '       d.   VP                  V4      w  rgV'       d    SP                  V4       \        V\        4      '       d   TMVP!                  V4      pV'       d   V! V4       K²  K´  K¶   Ve0   VP!                  VP#                  4       4      p
V
'       d	   V! V
4       S P%                  SW%RSP&                  V3R l4       R#   \         d    \        P                  R
RR7        L¼i ; i  \         d     KŽ  i ; i  \         d!   p	\        P                  RT	4        Rp	?	L¸Rp	?	ii ; i)z2Background thread: read output from a PTY process.r:   r¡   rÿ   N)ÚPtyQueryResponder)ÚrowsÚcolsc                ó(   € V ^8„  d   QhR\         RR/# rB  rÔ   )r(   s   "r)   r*   Ú6ProcessRegistry._pty_reader_loop.<locals>.__annotate__Û  s   € ÷ 	Cñ 	Cœð 	C ñ 	Cr+   c                 ó0   <€ SP                  SV R R7       R# )T)Úunless_exitedN)rû  )rC  r>  r   s   &€€r)   ÚingestÚ0ProcessRegistry._pty_reader_loop.<locals>.ingestÛ  s   ø€ ð ×Ñ ¨¸TÐÖBr+   r  zPTY query response write failedT)Úexc_infozPTY stdout reader ended: %sr£  c                  óD   <€ \        S R 4      '       d   S P                  # R# )Ú
exitstatusr?   )ÚhasattrrB  ©Úptys   €r)   r  Ú2ProcessRegistry._pty_reader_loop.<locals>.<lambda>ÿ  s   ø€ ´¸¸\×0JÒ0J˜cŸn™nÐRÐPRÐRr+   )rŠ  r  r  rª  Útools.pty_query_responderr7  Úisaliver  r~  Úbytesrc  Úwriter±   rF   r¯   rf   r°   Úflushr  rÖ  )r>  r   r
  Ú	responderr7  r>  rä  ÚrepliesrC  rÌ  r"  rE  s   ff         @r)   r¯  Ú ProcessRegistry._pty_reader_loopË  s‚  ú€ à�l‰lˆô ×.Ò.¨wÔ7¸yÔIˆð
 ˆ	ß‹{ÝCÙ)¨r¸Ô<ˆI÷	Cñ 	Cð	;Ø—+‘+—-’-ðØŸH™H T›N�Eßà$Ò0´ZÀÄu×5MÒ5MØ-6×->Ñ->¸uÓ-E™N˜Eß&ð!&Ø$'§I¡I¨gÔ$6ô )3°5¼#×(>Ò(>™uÀGÇNÁNÐSXÓDY˜ßÙ" 4žLñ  ñ ð  ð, Ò à—>‘> )§/¡/Ó"3Ó4ˆDßÙ�t”Ø×ÑØ�W eØ�H‰HÔRö	Tøô# (1ô !&Ü$*§L¡LØ(IØ15ð %1ö %&ð!&ûô !ô Úðûäô 	;Ü�L‰LÐ6¸×:Ñ:ûð	;úsl   ÁF Á-F Â5F Â<E% Ã0F Ã>F ÄF Å%"F
ÆF Æ	F
Æ
F ÆFÆF ÆFÆF ÆG
Æ*GÇG
r=  c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r&   r   rC  r=  r'   N)r!  rf   rs   )r(   rß   s   "€r)   r*   r°    s+   ø€ ÷ )ñ )¡nð )¹Cð )ÑSWð )Ðdhñ )r+   c               ó°   € V'       g   VP                  V4       MVP                  V4      '       g   R# V P                  W4       V P                  W4       R# )z¡Buffer a freshly-read chunk, then scan watch patterns and stream it live.
``unless_exited`` drops the chunk once the session has exited (atomically with a kill).N)rI  rN  r  rè  )r>  r   rC  r=  s   &&&$r)   rû  ÚProcessRegistry._ingest_output  sE   € ÷ Ø×!Ñ! $Õ'Ø×1Ñ1°$×7Ò7ÙØ×"Ñ" 7Ô1Ø×Ñ˜'Ö(r+   c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r&   r   rV  rW  r'   Nrå  )r(   rß   s   "€r)   r*   r°    s+   ø€ ÷ (ñ (¡nð (Éð (Ñadð (Ðnrñ (r+   c                ó¬   € VP                   ;_uu_ 4        VP                  W#V4       RRR4       V P                  V4       R#   + '       g   i     L#; i)zûMark a reader-observed exit (a raced kill keeps its own code/reason) and finish.
Under the session lock, like kill_process's commit: otherwise the kill can land between
mark_exited's ``killed`` check and its writes, and the reader overwrites the kill.N)rF  r]  Ú_move_to_finished)r>  r   r[  rV  rW  s   &&&&&r)   r!  ÚProcessRegistry._finish_exited  s8   € ð �]�]‹]Ø×Ñ 	°6Ô:÷ à×Ñ˜wÖ'÷ �]ús   •AÁA	c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  ©r!  rs   )r(   rß   s   "€r)   r*   r°    s   ø€ ÷ ñ ©ð ¹Dñ r+   c                ó|  € V P                   ;_uu_ 4        VP                  V P                  9   pV'       dR   RVn        \        P                  ! 4       Vn        \        V4       V P                  P                  VP                  4       WP                  VP                  &   RRR4        V P                  VX4       V'       g   VP                  '       g   VP                  P                  4        V#   + '       g   i     LY; i  X'       g   TP                  '       g   TP                  P                  4        i i ; i)züMove a session from running to finished.
Idempotent: kill_process() and the reader thread can both call this; only
the FIRST move enqueues the completion notification, so no duplicates.
Returns True when this call is the one that persisted the session.TN)rF  r`  r™  r…  r‘   rh  r    rè   rš  Ú_publish_finishedr„  r   )r>  r   Úwas_runnings   && r)   rT  Ú!ProcessRegistry._move_to_finished  sÚ   € ð
 �Z�Z‹ZØ!Ÿ*™*¨¯©Ñ5ˆKßØ*.�Ô'Ü$(§I¢I£K�Ô!ô & gÔ.Ø—‘×!Ñ! '§*¡*Ô-Ø)0�N‰N˜7Ÿ:™:Ñ&÷ ð&	0Ø×"Ñ" 7¨KÔ8÷  '×"9×"9Ð"9Ø×)Ñ)×-Ñ-Ô/ØÐ÷5 �Zû÷0  '×"9×"9Ð"9Ø×)Ñ)×-Ñ-Õ/ð #:ús   •BC1Â)D Ã1D	ÄD;ÄD;c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r&   r   rZ  r'   NrW  )r(   rß   s   "€r)   r*   r°  4  s"   ø€ ÷ 4ñ 4©ð 4Ádð 4Ètñ 4r+   c                óè  € V P                  V4       V P                  4        V'       dÉ   VP                  '       dµ   R RRVP                  RVP                  RVP
                  RVP                  RVP                  /VP                  '       d   RVP                  /M/ CV P                  V4      C\        V4      CRVP                  /Cp\        V4       V P                  P                  V4       R	# R	# R	# )
rË  Ú
completionr  ra  r<  r;  rì   rm  rf  N)Ú_release_finished_handlesrP  rx  r`  ra  r<  r;  rì   rm  Ú_exit_fieldsr3  rf  rÒ  rž  rÓ  )r>  r   rZ  rÕ  s   &&& r)   rY  Ú!ProcessRegistry._publish_finished4  sæ   € Ø×&Ñ& wÔ/Ø×ÑÔ ß˜7×5×5Ð5à˜Ø˜gŸj™jØ˜w×2Ñ2Ø˜7Ÿ?™?Ø ×!6Ñ!6Ø˜7Ÿ?™?ðð >E×=Q×=QÐ=Q�N G×$8Ñ$8Ñ9ÐWYðð ×#Ñ# GÓ,ðô % WÓ-ðð ˜g×0Ñ0ñˆLô # <Ô0Ø×!Ñ!×%Ñ% lÖ3ñ# 6‰;r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r  )r(   rß   s   "€r)   r*   r°  K  s   ø€ ÷ 
ñ 
™nð 
±ñ 
r+   c                óN   € R V P                   RV P                  RV P                  /# ©r[  rZ  r\  rd  r  s   &r)   r`  ÚProcessRegistry._exit_fieldsJ  s/   € ð ˜×*Ñ*Ø ×!:Ñ!:Ø  '×"<Ñ"<ð
ð 	
r+   c                ó    <€ V ^8„  d   QhRS[ /# rö  rN  )r(   rß   s   "€r)   r*   r°  R  s   ø€ ÷ %ñ %±ñ %r+   c                ón  € VP                   pVef   VP                  VP                  VP                  3 F>  pVf   K	  \	        \
        \        4      ;_uu_ 4        VP                  4        RRR4       K@  	  VP                  eŠ   VP                  p\        '       g6   Ve2   VP                  4       '       d   V\        P                  ! 4       Jd   R# \	        \        4      ;_uu_ 4        VP                  P                  4        RRR4       R# R#   + '       g   i     Kì  ; i  + '       g   i     R# ; i)u�  Close a finished session's OS handles (Popen pipes / PTY master).

Best-effort and idempotent: the session may have no local Popen (env
backends, detached recovery), or the handles may already be closed by
the reader loop / kill path. Closing a Popen's stream objects does not
kill anything â€” the child has already exited â€” it only releases the
parent's pipe FDs, which is exactly the retained-resource leak.
N)rc  r¼  r®   r�   r   rO   rD   rÅ  rŠ  r‡  rª  r¼  r�  Úcurrent_threadr±   )r>  r   rÏ  Ústreamrœ  s   &&   r)   r_  Ú)ProcessRegistry._release_finished_handlesR  sÚ   € ð �‰ˆØÒØŸ;™;¨¯©°T·Z±ZÓ@�ØÔ%Ü!¤'¬:×6Õ6ØŸ™œ÷ 7Ñ6ñ Að �<‰<Ò#ð ×+Ñ+ˆFß“K FÒ$6¸6¿?¹?×;LÒ;LØ¤i×&>Ò&>Ó&@Ó@Ùô œ)×$Õ$Ø—‘×"Ñ"Ô$÷ %Ñ$ñ $÷ 7×6Ð6ú÷" %×$Ð$ús   ÁDÃ(D#ÄD Ä#D4	c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  rW  )r(   rß   s   "€r)   r*   r°  v  s   ø€ ÷ >ñ >¡Nð >±tñ >r+   c                óä   € V P                   pV P                  P                  4       ;'       dD    V P                  P                  4       '       * ;'       d    VRJ;'       d    VP	                  4       # )zÏA reconcile saw the direct child exit and set ``exited``, but the reader that owns the
output is still on its final drain: the buffer is not the whole output yet, so nothing
may consume it as the completion.N)r‡  rˆ  r  r„  r¼  )r   rœ  s   & r)   Ú_reader_finalizingÚ"ProcessRegistry._reader_finalizingu  sj   € ð
 ×'Ñ'ˆØ×0Ñ0×7Ñ7Ó9÷ =ð =À'×B[ÑB[×BbÑBbÓBdÔ>d÷ =ð =Ø $Ð&÷=ð =Ø+1¯?©?Ó+<ð	>r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  rû   )r(   rß   s   "€r)   r*   r°  ~  s   ø€ ÷ 7ñ 7±ð 7¹ñ 7r+   c                ó   € WP                   9   # )zECheck if a completion notification was already consumed via wait/log.)r¡  )r>  r  s   &&r)   Úis_completion_consumedÚ&ProcessRegistry.is_completion_consumed~  s   € à×6Ñ6Ñ6Ð6r+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  rû   )r(   rß   s   "€r)   r*   r°  ‚  s   ø€ ÷ `ñ `©Sð `±Tñ `r+   c                ó\  € V P                   ;_uu_ 4        V'       d?   V P                  P                  V4      ;'       g    V P                  P                  V4      MRpRRR4       Xf   R# \	        \
        4      ;_uu_ 4        V P                  V4      pVf    RRR4       R# TpRRR4       VP                  '       * ;'       dB    VP                  ;'       d)    VP                  '       * ;'       d    VP                  ^ 8„  '       * #   + '       g   i     L²; i  + '       g   i     L}; i)a6  Whether a goal loop (``hermes_cli.goals`` wait barrier) should stay parked on
this session: still running AND, with ``watch_patterns``, none matched yet (a
long-lived watcher unblocks on its trigger, not on exit). Unknown/exited/
already-fired sessions return False so a stale barrier can never wedge the loop.NF)rF  r™  r†   rš  r   r±   rJ  r5  ry  r€  r~  )r>  r  r   Ú	refresheds   &&  r)   Úis_session_waitingÚ"ProcessRegistry.is_session_waiting‚  sæ   € ð
 �Z�Z‹Zß[e�t—}‘}×(Ñ(¨Ó4×VÐV¸¿¹×8JÑ8JÈ:Ó8VøÐkoˆG÷ àŠ?ÙÜ”i× Õ Ø×6Ñ6°wÓ?ˆIØÒ Ø÷ !Ñ ð  ˆG÷	 !ð
 —>‘>Ô!÷ `ð `Ø×"Ñ"×^Ð^¨7×+BÑ+BÔ'B×^Ð^Àw×GZÑGZÐ]^ÑG^ô'`ð 	`÷ �Zú÷ !× ús#   •*DÁ DÂDÂ$DÄD	ÄD+	rŸ   Úpoll_intervalr2   c                óP   <€ V ^8„  d   QhRS[ S[,          RS[R,          RS[RS[/# )r&   r<  rŸ   Nrx  r'   )r   rf   rŒ  r   )r(   rß   s   "€r)   r*   r°  “  s;   ø€ ÷ Qñ QÙ¡•}ðQÙ9>À½ðQÙ]bðQá	ñQr+   c          	     óÊ  € Vf   V P                  4       pR. R. R. /pV P                  ;_uu_ 4        V P                  V P                  3 UUu. uFh  qUP	                  4        FR  pVP
                  '       g   K  VP                  P                  4       '       d   K9  Ve   VP                  V8X  g   KP  VNKT  	  Kj  	  pppRRR4       X'       d   V^ 8:  d   V# V Uu. uF  qfP                  NK  	  upVR&   \        P                  RV\        V4      RP                  R V 4       4      4       \        P                  ! 4       \!        \#        V4      R4      ,           p\!        \#        V4      R	4      p	 ^ R
IHp
 RpV EF;  p VP                  P                  4       '       gÓ   V'       g   V
! 4       '       d   RpM»V\        P                  ! 4       ,
          pV^ 8:  d   M—\+        \(        4      ;_uu_ 4        V P-                  V4       V P/                  V4      f    RRR4       MQ RRR4       VP                  P                  4       '       d   M'VP                  P1                  \3        WÙ4      4       Kò   YLP                  P                  4       '       d   RMR,          P7                  VP                  4       EK>  	  VR,          '       d?   \        P9                  RV\        VR,          4      RP                  VR,          4      4       V# u uppi   + '       g   i     EL[; iu upi   \(         d    R p
 ELÃi ; i  + '       g   i     EL$; i  \4         d    Rp Lîi ; i)u-  Bounded linger for ``notify_on_complete`` background processes at one-shot exit.
A one-shot CLI run (``hermes -q/-Q/-z``) exits when its turn ends; a background
process it spawned still holds a stdout pipe owned by the dying parent and dies of
SIGPIPE seconds later (Bot Mode handoff replies were the visible casualty). Only
``notify_on_complete`` processes carry a completion contract â€” servers/daemons/
watchers aren't the parent's to wait for. ``task_id=None`` waits on every tracked
process; ``timeout=None`` reads ``terminal.oneshot_completion_wait_seconds`` (``<= 0``
disables). Each pass re-reconciles child state so an orphaned-pipe exit can't wedge
the linger. Returns ``{"waited", "completed", "timed_out"}`` id lists.

Bot Mode handoff REPLIES are the visible casualty (#90879): a recipient invoked as ``hermes -p <bot>
chat -Q --query-file ...`` dispatches its reply via ``message_agent`` / ``bot_relay`` exactly this
way, then exits, and the reply process is destroyed ~3s later. The sender waits forever for a reply
that was already killed.
See #17327.
NÚwaitedÚ	completedÚ	timed_outzZOne-shot exit lingering (bounded %ss) for %d notify_on_complete background process(es): %sú, c              3   ó8   "  € T F  qP                   x € K  	  R # 5ir  râ  ©r  r  s   & r)   r  Ú?ProcessRegistry.wait_for_pending_completions.<locals>.<genexpr>¸  s   é € Ð,C¹7°a¯T®T»7ùó   ‚r3   gš™™™™™©?)Úis_interruptedc                  ó   € R # )Fr/   r/   r+   r)   r  Ú>ProcessRegistry.wait_for_pending_completions.<locals>.<lambda>¾  s   € ¡er+   FTu‰   One-shot exit linger timed out after %ss with %d background process(es) still running: %s â€” they may be killed when this process exits.)Ú _oneshot_completion_wait_secondsrF  r™  rš  rÄ  rx  r„  r  r;  r`  rF   Úinfor0  rà  r‘   r’   rS   rŒ  Útools.interruptrƒ  r±   r   Ú_reconcile_local_exitrJ  rÖ  rQ   ÚKeyboardInterruptrN   rG   )r>  r<  rŸ   rx  r¶   Ústorer  ÚpendingÚdeadlinerÎ  Ú_is_interruptedÚinterruptedr   Ú	remainings   &&$$          r)   Úwait_for_pending_completionsÚ,ProcessRegistry.wait_for_pending_completions“  sÎ  € ð& Š?Ø×;Ñ;Ó=ˆGØ  " k°2°{ÀBÐGˆØ�Z�Z‹Zð
 !%§¡¨t¯~©~Ñ>ôÙ>�eÏÉÎÀ1Ø×'Õ'ô Ø01×0CÑ0C×0JÑ0J×0Lô à’_¨¯©¸7Ñ(B÷ �É‘Ñ>ð ñ ÷	 ÷ ˜' Qœ,ØˆMÙ*1Ó2©' QŸDœD©'Ñ2ˆˆxÑÜ�‰ð)à”S˜“\ 4§9¡9Ñ,C¹7Ó,CÓ#Cô	Eô —>’>Ó#¤c¬%°«.¸#Ó&>Õ>ˆÜ”u˜]Ó+¨TÓ2ˆð	,ÝIð ˆÜˆGð#Ø!×3Ñ3×:Ñ:×<Ò<ß"¡o×&7Ò&7Ø&*˜ØØ (¬4¯>ª>Ó+;Õ ;�IØ  A”~Øä!¤)×,Õ,ð ×2Ñ2°7Ô;Ø×9Ñ9¸'ÓBÒJØ!÷ -Ð,ð K÷ -ð ×0Ñ0×7Ñ7×9Ò9ØØ×-Ñ-×2Ñ2´3°yÓ3KÖLð- =ð6 ×";Ñ";×"BÑ"B×"DÒ"D‘;È+ÕV×]Ñ]Ð^e×^hÑ^h×iñ; ð< �+×ÔÜ�N‰Nð!ð œ˜V KÕ0Ó1°4·9±9¸VÀKÕ=PÓ3Qô	Sð
 ˆùóo÷	 �ZˆZüò 3øô ô 	,Ù+‹Oð	,ú÷ -×,Ð,ûô %ô #ð #’ð#ús›   ±LÁ&L

Á8L

ÂL

Â1
L

Â;LÃL$Å1L) Æ MÆ MÆ(MÆ5MÆ8#MÇMÇ3&L>ÈMÈ#'MÉ&MÌ
LÌL!	Ì)L;Ì:L;Ì>MÍ		MÍM"Í!M"c                ó    <€ V ^8„  d   QhRS[ /# r%   rk  )r(   rß   s   "€r)   r*   r°  ç  s   ø€ ÷ Yñ Y©eñ Yr+   c                 ó.   € \         P                  RR4      # )zTLinger (s) for one-shot exits with pending notify_on_complete processes; 0 disables.Úoneshot_completion_wait_secondsg     À‚@rn  r/   r+   r)   r†  Ú0ProcessRegistry._oneshot_completion_wait_secondsæ  s   € ô ×.Ñ.Ð/PÐRWÓXÐXr+   Úskip_poll_observedc                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r&   r  r—  r'   rû   )r(   rß   s   "€r)   r*   r°  ë  s(   ø€ ÷ 	uñ 	u©Sð 	uÉð 	uÑY]ñ 	ur+   c               ó^   € WP                   9   ;'       g    T;'       d    WP                  9   # )uÿ  Skip a completion the CLI agent already has this turn â€” consumed via wait/log
or observed inline via poll(). Gateway/tui watchers check only
``is_completion_consumed`` so a read-only poll never suppresses their turn.

Skips when the agent has either truly consumed the output (wait/log â†’ ``_completion_consumed``) or
observed the exit inline via poll() (``_poll_observed``). In both cases the CLI agent already has
the result this turn, so injecting a [SYSTEM: ...] completion would be a duplicate (#8228).
)r¡  r¢  )r>  r  r—  s   &&$r)   Ú_drain_should_skipÚ"ProcessRegistry._drain_should_skipë  s.   € ð ×6Ñ6Ñ6×tÐtÐ;M×;sÐ;sÐR\×`sÑ`sÑRsÐtr+   c                ó    <€ V ^8„  d   QhRS[ /# r%   r˜   )r(   rß   s   "€r)   r*   r°  ÷  s   ø€ ÷ ñ ±$ñ r+   c                 óh   €  \        \        P                  RRR4      4      #   \         d     R# i ; i)um   ``delegation.surface_child_process_notifications``; False on any config
error â€” never crash the drain loop.Ú
delegationÚ#surface_child_process_notificationsF)rs   r—  rc  r±   r/   r+   r)   Ú$_surface_child_process_notificationsÚ4ProcessRegistry._surface_child_process_notificationsö  s5   € ð	Üœ×5Ñ5°lÐDiÐkpÓqÓrÐrøÜô 	Úð	ús   ‚" ¢1°1c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# )r&   Úevtra  Úis_async_delegationr'   ræ   )r(   rß   s   "€r)   r*   r°     s1   ø€ ÷ Añ A™ð A©Cð AÑRVð AÑ[_ñ Ar+   c                ón  € \        V P                  R4      ;'       g    R4      pT;'       g%    \        T;'       g    V P                  R4      4      pVe   V'       d    \        V! V 4      4      # V'       d   V'       d   WA8H  # T;'       d    V P                  R4      '       * #   \         d     R# i ; i)zQRouting verdict for one drained event (see drain_notifications); False = requeue.ra  r9   Úorigin_ui_session_idFÚrestored)rf   r†   rs   r±   )r£  ra  Ú
owns_eventr¤  Úevt_session_keyÚrequires_positive_proofs   &&&&  r)   Ú_owns_eventÚProcessRegistry._owns_eventÿ  s¥   € ô ˜cŸg™g mÓ4×:Ð:¸Ó;ˆØ"5×"qÐ"q¼¸o×>pÐ>pÐQT×QXÑQXÐYoÓQpÓ9qÐØÒ!×&=ðÜ™J s›OÓ,Ð,÷ ×2Ø"Ñ1Ð1ð (×?Ð?¨C¯G©G°JÓ,?Ô@Ð@øô ô Úðús   Á B% Â%B4Â3B4c                ó    <€ V ^8„  d   QhRS[ /# r%   r5   )r(   rß   s   "€r)   r*   r°    s   ø€ ÷ .ñ .¡Sñ .r+   c                ó"  € V P                   '       d   ^ # RV n         ^ RIHpHp V! R4      p ^ RIHp V! V P                  4      V! V4       #   \         d*   p\        P                  RT4        Rp?T! T4       ^ # Rp?ii ; i  T! T4       i ; i)aS  Rehydrate durable delegation completions from the LAUNCH profile's ledger, once per
process. Called by the first consumer that drains the queue (CLI/TUI drain, gateway boot,
TUI poller) so a mere ``import model_tools`` never touches state.db (#123265). The replay
always runs in the launch scope: the TUI poller / prompt_turn drain call this under the
session's profile binding, and a once-per-process replay taken under a secondary's scope
would leave the launch ledger unreplayed for the life of the process. Secondaries are
replayed by the gateway's ``_restore_secondary_completion_ledgers``.T)Úreset_hermes_home_overrideÚset_hermes_home_overrideN)Úrestore_undelivered_completionsz2Could not restore async delegation completions: %s)
Ú_completions_restoredÚhermes_constantsr¯  r°  rŸ  r±  rž  r±   rF   rG   )r>  r¯  r°  Útokenr±  r·   s   &     r)   Úrestore_completionsÚ#ProcessRegistry.restore_completions  s€   € ð ×%×%Ð%ÙØ%)ˆÔ"ßYÙ(¨Ó.ˆð	.ÝNÙ2°4×3HÑ3HÓIñ
 ' uÕ-øô	 ô 	Ü�N‰NÐOÐQTÔUÛá& uÖ-ûð		ûñ ' uÕ-ús)   ­A ÁBÁA<Á.B Á<BÂB Â
Bc          	      óR   <€ V ^8„  d   QhRS[ RS[RS[S[S[S[ 3,          ,          /# )r&   ra  r—  r'   )rf   rs   rg   Útupler   )r(   rß   s   "€r)   r*   r°  %  s3   ø€ ÷ 5ñ 5Ùð5ÙMQð5á	‰e‘D™#�IÕÕ	ñ5r+   c               óª  € V P                  4        . p. pRpV P                  P                  4       '       Egf    V P                  P                  4       pTP                  R4      R8H  pT P                  YqY(4      '       g   TP                  T4       K{  TP                  RR4      p	TP                  R4      R8X  d   T P                  Y“R7      '       d   K½  \        TP                  R4      ;'       g    TP                  R	4      ;'       g    R4      p
\        T4      '       dQ   Tf   T P                  4       p\        YvR
7      '       g+   \        P                  RTP                  RR4      Yš4       EK[  \        T4      ;p'       g   EKq  TP                  Y{34       EK†  V F  pV P                  P!                  V4       K   	  V#   \         d     K4  i ; i)ah  Pop all pending events and return ``(raw_event, formatted_text)`` pairs.
Skips completions per ``_drain_should_skip`` (gateway/TUI pass
``skip_poll_observed=False``). Routing (``_owns_event``): async-delegation events
always need ownership proof, ordinary events once they carry ``session_key`` or
``origin_ui_session_id``; ``owns_event(evt)`` (strongest; the TUI passes a
compression-chain-aware check) consumes ONLY on True, ``session_key`` uses plain
equality; non-owned events are re-queued for their owner. No filter consumes
everything (legacy single-session) except restored delegation payloads (fail-closed).NrË  Úasync_delegationr  r9   r^  )r—  r;  r<  )Úsurface_childz‡Suppressed subagent-owned process notification (delegation.surface_child_process_notifications=false): type=%s session_id=%s task_id=%s)rµ  rž  ÚemptyÚ
get_nowaitr±   r†   r«  rN   rš  rf   r   r   r   rF   r¯   r   rÓ  )r>  ra  r¨  r—  ÚresultsÚrequeuer»  r£  r¤  Ú_evt_sidÚ_evt_task_idrC  s   &&&$        r)   Údrain_notificationsÚ#ProcessRegistry.drain_notifications%  s¤  € ð 	× Ñ Ô"Ø*,ˆØ ˆð &*ˆØ×'Ñ'×-Ñ-×/Ó/ðØ×+Ñ+×6Ñ6Ó8�ð #&§'¡'¨&£/Ð5GÑ"GÐØ×#Ñ# C°j×VÒVØ—‘˜sÔ#Ùð —w‘w˜|¨RÓ0ˆHØ�w‰w�v‹ ,Ô.°4×3JÑ3JØð 4K÷ 4Aò 4Aáô ˜sŸw™w Ó7×SÐS¸3¿7¹7À9Ó;M×SÐSÐQSÓTˆLÜ,¨S×1Ò1Ø Ò(Ø$(×$MÑ$MÓ$O�MÜ2°3×TÓTÜ—L‘Lð;ð Ÿ™ ¨Ó5°xô	Oò
 Ü2°3Ó7Ð7ˆt×7Ñ7Ø—‘ ˜{×+ÛˆCØ×!Ñ!×%Ñ% cÖ*ñ àˆøôC ô Úðús   ¹G ÇGÇGc                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# r  ©rf   r   r!  )r(   rß   s   "€r)   r*   r°  _  s$   ø€ ÷ 	tñ 	t™cð 	t¡h©~Õ&>ñ 	tr+   c                ó®  € \        V\        4      '       d	   V'       g   R# V P                  ;_uu_ 4        V P                  P	                  V4      ;'       g    V P
                  P	                  V4      pRRR4       Xf   \        V4      P	                  V4      pT P                  Ve   V4      # V P                  V4      4      #   + '       g   i     LX; i)z›Session by full ID or unique prefix (``proc_4dae`` / bare ``4dae``, like git
short hashes); ambiguous or too-short prefixes resolve to None, never a guess.N)	r~  rf   rF  r™  r†   rš  r   rJ  Ú_resolve_prefix)r>  r  r   s   && r)   r†   ÚProcessRegistry.get_  sœ   € ô ˜*¤c×*Ò*·*ÙØ�Z�Z‹ZØ—m‘m×'Ñ'¨
Ó3×UÐU°t·~±~×7IÑ7IÈ*Ó7UˆG÷ àŠ?Ü,¨ZÓ8×<Ñ<¸ZÓHˆGØ×-Ñ-¸Ò9L¨gÓsÐsÐRV×RfÑRfÐgqÓRrÓsÐs÷	 �Zús   µ?CÃC	c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# r  rÅ  )r(   rß   s   "€r)   r*   r°  j  s$   ø€ ÷ Kñ K©#ð K±(¹>Õ2Jñ Kr+   c                ó¼  € \        V\        4      '       d   VP                  4       MRpV'       g   R# VP                  R4      '       g   RV 2p\	        V4      \	        R4      ,
          V P
                  8  d   R# \        V4      pV P                  ;_uu_ 4        TP                  V P                  V P                  3 UUUu/ uF7  pVP                  4        F   w  rVVP                  V4      '       g   K  WVbK"  	  K9  	  uppp4       RRR4       \	        V4      ^8X  d#   \        \        VP                  4       4      4      # R# u upppi   + '       g   i     LK; i)zuResolve a unique session-ID prefix (a bare hex tail is normalized to
``proc_<tail>``); :meth:`get` tries exact first.r9   Nrt  )r~  rf   rC   rJ   r0  Ú_MIN_PREFIX_CHARSr   rF  Úupdater™  rš  Úitemsrö  ÚiterrÄ  )r>  r  ÚqueryÚmatchesr‹  Úsidr  s   &&     r)   rÇ  ÚProcessRegistry._resolve_prefixj  s  € ô '1°¼S×&AÒ&A�
× Ñ Ô"ÀrˆßÙØ×Ñ ×(Ò(Ø˜E˜7�OˆEÜˆu‹:œ˜G›Õ$ t×'=Ñ'=Ô=ÙÜ(¨Ó/ˆØ�Z�Z‹ZØ�N‰NØ%)§]¡]°D·N±NÑ$CõÙ$C˜5Ø#Ÿk™kžm‘F�C¨s¯~©~¸e×/Dô �’Ù+ñ Ñ$Cóô ÷ ô
 03°7«|¸qÔ/@Œt”D˜Ÿ™Ó)Ó*Ó+ÐJÀdÐJùô	÷ �Zús$   Â(EÃ.EÃ5
EÃ?	EÅEÅE	c                ó$   <€ V ^8„  d   QhRS[ RR/# rM  rN  )r(   rß   s   "€r)   r*   r°  |  s   ø€ ÷ I(ñ I(©^ð I(Àñ I(r+   c           	     óD  € Ve   VP                   '       d   R# \        VRR4      pVf   R#  VP                  4       pTf   R# TP                  p\
        '       g¿   TP                  '       d­   Te©   TP                  4       '       d“   TP                  P                  4        TP                  P                  \        4      '       d   R# TP                  ;_uu_ 4        TP                  T4       RRR4       \        P!                  RTP"                  T4       R# \        TRR4      pTEe(   \
        '       Eg    ^ RIpTP'                  4       pTP%                  YvP(                  4      pTP%                  YvP*                  T\,        P.                  ,          4        \1        \2        \4        \6        4      ;_uu_ 4        TP9                  4       p	T	'       d;   TP;                  \=        T	\>        4      '       d   T	MT	PA                  RRR7      4       RRR4       \1        \        4      ;_uu_ 4        TP%                  YvP*                  T4       RRR4       TP                  ;_uu_ 4        TP                  T4       RRR4       \        P!                  R	TP"                  T4       T PE                  T4       R#   \         d     R# i ; i  + '       g   i     ELá; i  + '       g   i     LÔ; i  + '       g   i     L«; i  \1        \        4      ;_uu_ 4        TP%                  YvP*                  T4       RRR4       i   + '       g   i     i ; i; i  \         d-   p
\        PC                  RTP"                  T
4        Rp
?
EL4Rp
?
ii ; i  + '       g   i     EL; i)
u=  Reconcile ``session.exited`` against the real child state.
The reader flips ``exited`` only at EOF; when the direct child has exited but a
descendant (e.g. a daemon from ``hermes update``) holds the pipe open, poll()
would report "running" forever. If ``Popen.poll()`` has an exit code, drain
readable bytes non-blocking and flip ``exited``. No-op for env/PTY, exited and
detached sessions.

The reader thread (`_reader_loop`) sets `session.exited = True` only in its `finally` block, which
runs when `stdout.read()` returns EOF. If the direct `Popen` child has exited but a descendant
process (e.g. a daemon spawned by `hermes update` restarting the gateway) is still holding the
stdout pipe open, the reader blocks forever and poll() keeps returning "running" indefinitely (issue
#17327 â€” 74 polls over 7 minutes on Feishu).
Nrc  zxReconciled session %s: direct child exited with code %s; reader will publish the owned completion after its final drain.r¼  r:   r¡   rÿ   z$Non-blocking drain failed for %s: %szxReconciled session %s: direct child exited with code %s but reader was still blocked (orphaned pipe). Flipped to exited.)#r5  r  r  r±   r‡  rª  r‰  r¼  rˆ  r   r„  rÖ  Ú _READER_FINAL_DRAIN_WAIT_SECONDSrF  r]  rF   r‡  r`  Úfcntlr  ÚF_GETFLÚF_SETFLrA   Ú
O_NONBLOCKr   ÚBlockingIOErrorrO   rD   r  rI  r~  rf   r°   r¯   rT  )r>  r   rÏ  Úrcrœ  r¼  rÖ  r  Úflagsrä  rÌ  s   &&         r)   r‰  Ú%ProcessRegistry._reconcile_local_exit|  sŒ  € ð Š?˜gŸnŸn˜nÙÜ�w 	¨4Ó0ˆØŠ<Ùð	Ø—‘“ˆBð Š:ÙØ×'Ñ'ˆç“Ø×*×*Ð*ØÒ"Ø—‘×!Ò!ð ×,Ñ,×0Ñ0Ô2ð ×(Ñ(×-Ñ-Ô.N×OÒOÙØ——“Ø×#Ñ# BÔ'÷ ä�K‰KðRà—
‘
˜Bô ñ ä˜˜x¨Ó.ˆØÓ§k¤kðTÛØ—]‘]“_�ØŸ™ B¯©Ó6�Ø—‘˜B§¡¨u´r·}±}Õ/DÔEð>Ü!¤/´7¼J×GÕGØ &§¡£˜ß Ø#×1Ñ1¼:ÀeÌS×;QÒ;Q±%ÐW\×WcÑWcÐdkÐt}ÐWcÓW~Ô÷ Hô
 "¤)×,Õ,ØŸ™ B¯©°uÔ=÷ -ð �]�]‹]Ø×Ñ Ô#÷ ä�‰ðDà�J‰J˜ô	ð 	×Ñ˜wÖ'øôi ô 	Úð	ú÷* —�ú÷  H×Gú÷
 -×,ûœ¤)×,Õ,ØŸ™ B¯©°uÔ=÷ -×,×,Ð,þäô TÜ—‘ÐCÀWÇZÁZÐQR×SÒSûðTúç�]ˆ]ús©   ­J4 ÃKÄ9A M Æ!L  Æ;AKÈL  ÈM È-K-É
M É&NÊ4KËKËK	ËK*	Ë%L  Ë-K=	Ë8M Ë=M Ì MÌL>	Ì5	MÌ>MÍ	MÍM ÍNÍ!NÎNÎN	c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r  )r(   rß   s   "€r)   r*   r°  È  s   ø€ ÷ {ñ {™nð {±ñ {r+   c                ód   € R V P                   RV P                  RV P                  '       d   R/# R/# )r  rì   r  r5  r?  )r`  rì   r5  r  s   &r)   Ú_status_headÚProcessRegistry._status_headÇ  s3   € à˜gŸj™j¨)°W·_±_ÀhÐ\c×\j×\jÐ\jÐPXÐzÐzÐpyÐzÐzr+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r  )r(   rß   s   "€r)   r*   r°  Ë  s   ø€ ÷ ñ ™sð ¡tñ r+   c                óî  € V P                  V4      pVe   V P                  V4      '       d   \        V4      # V P                  V4       VP                  ;_uu_ 4        \        VR4      pVP                  V P                  V4      rTRRR4       / V P                  V4      CRVP                  R\        \        P                  ! 4       VP                  ,
          4      RX/CpX'       dD   VP                  V P                  V4      4       X'       g   V P                  P!                  V4       VP"                  '       d&   VP$                  '       g   VP                  RRR7       V#   + '       g   i     Læ; i)	z9Check status and get new output for a background process.Néè  rb  Úuptime_secondsÚoutput_previewTz=Process recovered after restart -- output history unavailable)ri  Únote)r†   rX  r  r‰  rF  r(  r5  rm  rà  rb  r6   r‘   rf  rÌ  r`  r¢  Úaddri  ro  )r>  r  r   ræ  r5  Ú
finalizingr¶   s   &&     r)   r  ÚProcessRegistry.pollË  s&  € à—(‘(˜:Ó&ˆØŠ?˜d×4Ñ4°W×=Ò=Ü˜jÓ)Ð)Ø×"Ñ" 7Ô+ð �]�]‹]Ü)¨'°4Ó8ˆNØ!(§¡°×1HÑ1HÈÓ1Q�J÷ ðgØ×Ñ Ó(ðgØ*/°·±Øœc¤$§)¢)£+°×0BÑ0BÕ"BÓCÐEUÐWeñgˆ÷ Ø�M‰M˜$×+Ñ+¨GÓ4Ô5÷
 Ø×#Ñ#×'Ñ'¨
Ô3Ø××Ð G×$6×$6Ð$6Ø�M‰M 4Ð.mˆMÔnØˆ÷! �]ús   Á)E$Å$E4	c                ó@   <€ V ^8„  d   QhRS[ RS[R,          RS[RS[/# )r&   r  ÚoffsetNr1  r'   ©rf   r6   r   )r(   rß   s   "€r)   r*   r°  å  s.   ø€ ÷ ñ ¡3ð ±°dµ
ð É#ð ÑX\ñ r+   c           	     ó.  € ^ RI Hp V P                  V4      pVf   \        V4      # VP                  ;_uu_ 4        V! VP
                  4      pVP                  V P                  V4      r‡RRR4       XP                  4       p	\        V	4      p
Vf&   V^ 8”  d   W“) R p\        V4      ;'       g    V
^ 8H  pMbT;'       g    ^ pW’W#,            p\        W"V,           4      P                  V
4      ^,          pV
^ 8H  ;'       g    \        V4      ;'       d    WÚ8H  p/ V P                  V4      CRRP                  V4      RV
R\        V4       R2/CpX'       d,   V'       d$   X'       g   V P                  P!                  V4       V#   + '       g   i     EL"; i)z;Read the full output log with optional pagination by lines.r$  Nr,  rÙ  Útotal_linesÚshowingz lines)r&  r%  r†   r  rF  r'  r5  rm  rI   r0  rs   ÚsliceÚindicesrà  rà  r¡  rè  )r>  r  rì  r1  r%  r   Úfull_outputr5  ré  rÜ  rï  ÚselectedÚobserved_completion_outputrþ   r¶   s   &&&&           r)   Úread_logÚProcessRegistry.read_logå  sh  € å/à—(‘(˜:Ó&ˆØŠ?Ü˜jÓ)Ð)Ø�]�]‹]Ù$ W×%:Ñ%:Ó;ˆKØ!(§¡°×1HÑ1HÈÓ1Q�J÷ ð ×&Ñ&Ó(ˆÜ˜%“jˆð Š>˜e aœiØ˜V˜W�~ˆHÜ)-¨h«×)KÐ)K¸;È!Ñ;KÑ&à—[�[˜qˆFØ F¥NÐ3ˆHÜ˜¨%¥Ó0×8Ñ8¸ÓEÀaÕHˆDØ)4¸Ñ)9×)eÐ)e¼dÀ8»n×>dÐ>dÐQUÑQdÐ&ðMØ×Ñ Ó(ðMØ*2°D·I±I¸hÓ4GØ˜;¨	´c¸(³m°_ÀFÐ3KñMˆ÷ ×0¿Ø×%Ñ%×)Ñ)¨*Ô5Øˆ÷+ �]ˆ]ús   »/FÆF	c                ó:   <€ V ^8„  d   QhRS[ RS[R,          RS[/# )r&   r  rŸ   Nr'   rí  )r(   rß   s   "€r)   r*   r°    s+   ø€ ÷ Eñ E™sð E©S°4­Zð EÁ4ñ Er+   c           
     ó´  € ^ RI HpHp  \        \        P
                  ! RR4      4      pVe   V^ 8:  d   RRRRV R2/# RpT;'       g    TpV'       d   W%8”  d   TpR	V R
V R2pV P                  V4      pVf   \        V4      # \        P                  ! 4       V,           p	\        P                  ! 4       V	8  Eda   V P                  V4      pVf   \        V4      # V P                  V4       Rp
VP                  '       dF   V P                  V4      '       g/   V P                   P#                  V4       V P%                  VR4      p
MwV! 4       '       d    RRRVP&                  R\)        VR4      RR/p
MKV! \*        P,                  ! 4       P.                  4      '       d!   RRRVP&                  R\)        VR4      RRRR/p
V
e   V'       d   WjR&   V
# V	\        P                  ! 4       ,
          pV^ 8:  d   M)VP0                  P3                  \5        RV4      R7       EK{  RRRVP&                  R\)        VR4      RR/p
RV R2pVP6                  '       d;   VR\        \        P                  ! 4       VP6                  ,
          4       R2,          pTVP8                  '       d   RMR,          pV'       d   V R V 2MTV
R&   V
#   \        \        3 d    ^´p EL¬i ; i)!u9  Block until the process exits, the timeout elapses, the user interrupts, or a
mid-turn user message (steer/redirect â†’ ``request_yield``) releases the wait.
``timeout`` defaults to (and is clamped by) TERMINAL_TIMEOUT. Returns a dict
with status exited|timeout|interrupted|not_found|error and an output snapshot.)Úconsume_yieldrƒ  ÚTERMINAL_TIMEOUTÚ180Nr  r  ztimeout must be positive (got Ú)zRequested wait of z%s was clamped to configured limit of r  r5  r�  rì   r,  rä  rç  z+User sent a new message -- wait interruptedÚprocess_runningTz�User sent a new message -- wait released; the process is still running and you will be notified on exit. Respond to the user now.Útimeout_noter2   rÔ  rŸ   zWait window of uA   s elapsed â€” the process is still running. This is not an error.z	 Uptime: r"  uc    notify_on_complete is set: you will be notified on exit â€” do more work instead of waiting again.zq Poll again later or use terminal(background=true, notify_on_complete=true) next time for automatic notification.z. )rˆ  rú  rƒ  r6   rA   rB   rD   rT   r†   r  r‘   r’   rJ  r‰  r5  rm  r¡  rè  Ú_exit_snapshotrì   r(  r�  rh  Úidentr„  rÖ  rQ   rf  rx  )r>  r  rŸ   Ú_consume_yieldrŽ  Úmax_timeoutrÿ  Úeffective_timeoutr   r�  r¶   r�  Ú	base_notes   &&&          r)   rÖ  ÚProcessRegistry.wait  sÝ  € ÷
 	gð	ÜœbŸišiÐ(:¸EÓBÓCˆKð
 Ò 7¨a¤<Ø˜g wÐ2PÐQXÐPYÐYZÐ0[Ð\Ð\ØˆØ#×2Ð2 {Ðß�wÔ,Ø +ÐØ/°¨yÐ8]Ð^iÐ]jÐjkÐlˆLØ—(‘(˜:Ó&ˆØŠ?Ü˜jÓ)Ð)Ü—>’>Ó#Ð&7Õ7ˆÜ�nŠnÓ Õ)Ø×4Ñ4°WÓ=ˆGØŠÜ! *Ó-Ð-Ø×&Ñ& wÔ/ØˆFØ�~�~ˆ~ d×&=Ñ&=¸g×&FÒ&FØ×)Ñ)×-Ñ-¨jÔ9Ø×,Ñ,¨W°hÓ?‘Ù ×"Ò"à˜m¨Y¸¿¹ÈÔS_Ð`gÐimÓSnØÐIðK‘ñ  ¤	× 8Ò 8Ó :× @Ñ @×AÒAð ˜m¨Y¸¿¹ÈÔS_Ð`gÐimÓSnØ% tØð bðd�ð
 Ò!ßØ-9˜>Ñ*Ø�Ø ¤4§>¢>Ó#3Õ3ˆIØ˜AŒ~ØØ×%Ñ%×*Ñ*´3°s¸IÓ3FÐ*×Gà�i ¨G¯O©O¸XÄ|ÐT[Ð]aÓGbà˜tð%ˆð
 Ð/Ð0Ð0qÐrð 	à××ÐØ˜9¤S¬¯ª«°w×7IÑ7IÕ)IÓ%JÐ$KÈ2ÐNÕNˆIØà×)×)Ð)ñ rðMõ	Nˆ	÷
 DP L >°°I°;Ñ!?ÐU^ˆˆ~ÑØˆøôy œIÐ&ô 	Ø‹Kð	ús   Š K  Ë KËKc                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r&   r   r  r'   r   )r(   rß   s   "€r)   r*   r°  K  s'   ø€ ÷ Tñ T¡ð T¹ð TÁñ Tr+   c                ób   € RVRV P                   /\        P                  V 4      C\        V 4      C# )zTResult dict for an exited session: exit metadata + the completion-sized output tail.r  rì   )rì   r—  r`  r3  )r   r  s   &&r)   r   ÚProcessRegistry._exit_snapshotJ  s?   € ð �f˜i¨¯©ðTä×*Ñ*¨7Ó3ðTä7IÈ'Ó7RðTð 	Tr+   rW  zprocess.killÚconsume_outputc                ó2   <€ V ^8„  d   QhRS[ RS[ RS[RS[/# )r&   r  rW  r
  r'   )rf   rs   r   )r(   rß   s   "€r)   r*   r°  Q  s3   ø€ ÷ ^8ñ ^8Ùð^8Ù*-ð^8ÙPTð^8á	ñ^8r+   c          
     óê  € V P                  V4      pVf   \        V4      # VP                  '       d–   V P                  V4      pVP                  ;_uu_ 4        V P                  VR4      pV P                  V4      pRRR4       V'       g   VP                  XR&   V'       d$   X'       g   V P                  P                  V4       X#  V P                  WAV4      pVe   V# V P                  V4      pVP                  ;_uu_ 4        VP                  p	RRR4       X	'       d   . MV P                  V4      p
V
'       dq   RP                  \        \        V
4      4      p\        P!                  RVP"                  \%        V
4      V4       RRRR\%        V
4       R	V R
2RVP"                  RV
RR/# V'       gˆ   VP                  ;_uu_ 4        VP                  pRRR4       \        P!                  RVP"                  VP                  4       RRRRVP                   R2RVP"                  RVP                  RX'       * /# VP                  ;_uu_ 4        \'        V4      pV'       d   V P                  P                  V4       RVn        RVn        RVn        W$n        RRR4       V P/                  V4      '       g   \1        V4       V P3                  4        RRRVP"                  RVP*                  RVP,                  /XC#   + '       g   i     ELŒ; i  + '       g   i     EL	; i  + '       g   i     ELY; i  + '       g   i     L¨; i  \4         d   pRRR\        T4      /u Rp?# Rp?ii ; i)ul  Kill a background process and return its output snapshot.
``consume_output`` is true for explicit tool/RPC kills (the caller sees the
output). Bulk cleanup passes false so it doesn't suppress an autonomous
completion notification â€” except abandoned-turn reaping (``kill_started_since``),
which passes true so a killed abandoned process can't revive stopped work.NÚalready_exitedÚscope_stop_failedr~  uP   Kill incomplete for %s: %d process(es) still alive (%s) â€” session kept runningr  r  zKill incomplete: z process(es) still alive (z); session runningr  Ú	survivorsrþ  Tz5Kill incomplete for %s: systemd scope %s did not stopzKill incomplete: systemd scope z did not stoprY  rZ  r\  iñÿÿÿ)r†   r  r5  Ú_stop_scoperF  r   rm  rk  r¡  rè  Ú_signal_killÚ_post_kill_survivorsrà  rì  rf   rF   rG   r`  r0  r3  r[  rZ  r\  rT  r    rP  r±   )r>  r  rW  r
  r   Úscope_stoppedr¶   ré  ÚearlyÚsignal_race_exitedr  ÚaliveÚroot_exitedr,  rÌ  s   &&$$           r)   Úkill_processÚProcessRegistry.kill_processQ  sú  € ð —(‘(˜:Ó&ˆØŠ?Ü˜jÓ)Ð)Ø�>�>ˆ>ð !×,Ñ,¨WÓ5ˆMØ——“Ø×,Ñ,¨WÐ6FÓG�Ø!×4Ñ4°WÓ=�
÷ ÷ !Ø.5×.BÑ.B�Ð*Ñ+÷ §jØ×)Ñ)×-Ñ-¨jÔ9ØˆMð?	8Ø×%Ñ% g¸>ÓJˆEØÒ Ø�ð !×,Ñ,¨WÓ5ˆMð ——“Ø%,§^¡^Ð"÷ ÷ 1™°d×6OÑ6OÐPWÓ6XˆIßØŸ	™	¤#¤c¨9Ó"5Ó6�Ü—‘ØfØ—J‘J¤ I£°ô7ð ˜gØØ+¬C°	«NÐ+;ð <Ø!˜7Ð"4ð6à  '§*¡*¨k¸9Ø% tð-ð -÷ !Ø—]—]“]Ø")§.¡.�K÷ #ä—‘ÐVØ&Ÿz™z¨7×+?Ñ+?ôAð ˜gØÐ>¸w×?SÑ?SÐ>TÐTaÐbØ  '§*¡*Ð.AÀ7×CWÑCWØ%¨;¤ð	8ð 8ð ——“Ü+¨GÓ4�ß!Ø×-Ñ-×1Ñ1°*Ô=Ø!%�”Ø$'�Ô!Ø,4�Ô)Ø-3Ô*÷ ð ×)Ñ)¨'×2Ò2Ü% gÔ.Ø×"Ñ"Ô$à˜( L°'·*±*Ð>QÐSZ×SlÑSlØ$ g×&@Ñ&@ðLàDJðLð L÷K —�ú÷, —�ú÷* #—]�]ú÷ —ûô$ ô 	8Ø˜g w´°A³Ð7Õ7ûð	8ús    Á$K?Ã	M Ã!%M ÄLÄM Ä#M Ä>A/M Æ.M Æ6M Ç
L'ÇA%M È=M ÉA
L;ÊM Ê:AM Ë?L	ÌL$	Ì	M Ì'L8	Ì2	M Ì;M	ÍM ÍM2ÍM-Í'M2Í-M2c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  rW  )r(   rß   s   "€r)   r*   r°  ²  s   ø€ ÷ ñ ™^ð ±ñ r+   c                óp   € V P                   '       g   R# \        V P                   4      pV'       * V n        V# )z­Stop the session's systemd scope: True when it has none or the stop worked. Every kill
path stops the scope through here, so a failed stop always leaves it marked for retry.T)rk  r	  r†  )r   Ústoppeds   & r)   r  ÚProcessRegistry._stop_scope±  s2   € ð ×#×#Ð#ÙÜ$ W×%9Ñ%9Ó:ˆØ*1¤kˆÔ#Øˆr+   c          	      óB   <€ V ^8„  d   QhRS[ RS[RS[RS[S[,          /# )r&   r   r  r
  r'   )r!  rf   rs   r   r   )r(   rß   s   "€r)   r*   r°  »  s1   ø€ ÷ 2ñ 2¡Nð 2Áð 2ÑUYð 2Ñ^fÑgkÕ^lñ 2r+   c                ó’  € VP                   '       d     VP                   P                  RR7       R# VP                  '       d3   V P                  VP                  P                  VP                  4       R# VP                  '       d@   VP                  '       d.   VP                  P                  RVP                   R2^R7       R# VP                  '       Ed   VP                  R8X  dó   VP                  '       dá   V P                  VP                  VP                  4      R8w  d™   V P!                  V4      pVP"                  ;_uu_ 4        \%        V4      pRRR4       V'       d   V P&                  P)                  V4       V P+                  V4       R	R
RVP,                  /XCpV'       g   VP.                  VR&   V# V P                  VP                  4       R# R	RRR/#   \         dF    TP                  '       d0   \        P
                  ! TP                  \        P                  4        R# i ; i  + '       g   i     Lå; i)zÈDeliver the kill via PTY, local Popen tree, sandbox exec or recovered host
PID. Returns a final result dict when the kill cannot proceed (recycled/dead
recovered PID, or no runtime handle), else None.T)Úforcezkill r'  rÔ  r6  r?  Nr  r  r[  r  r  zkRecovered process cannot be killed after restart because its original runtime handle is no longer available)rŠ  Ú	terminater±   rb  rA   ÚkillÚsignalÚSIGTERMrc  rÕ  rg  rd  rë  ri  rj  rC  r  rF  r3  r¡  rè  rH  r[  rk  )r>  r   r  r
  r  r,  r¶   s   &&&&   r)   r  ÚProcessRegistry._signal_kill»  sÜ  € ð �<�<ˆ<ð9Ø—‘×&Ñ&¨TÐ&Ô2ñX ðQ �_�_ˆ_ð ×$Ñ$ W§_¡_×%8Ñ%8¸'×:QÑ:QÔRñJ ðI �_�_ˆ_ §§ Ø�O‰O×#Ñ# e¨G¯K©K¨=¸Ð$EÈqÐ#ÔQñF ðE ××Ñ '×"3Ñ"3°vÔ"=À'Ç+Ç+À+ð ×'Ñ'¨¯©°W×5LÑ5LÓMÐQZÔZØ $× 0Ñ 0°Ó 9�Ø—]—]“]Ü/°Ó8�F÷ #ç!Ø×-Ñ-×1Ñ1°*Ô=ð ×+Ñ+¨GÔ4Ø"Ð$4°kÀ7×CTÑCTÐ_ÐX^Ð_�ß$Ø29×2FÑ2F�FÐ.Ñ/Ø�ð ×$Ñ$ W§[¡[Ô1ñ ð	 ˜'Øð Nðð øôE ô 9Ø—;—;�;Ü—G’G˜GŸK™K¬¯©Ô8øñR ðW9ú÷$ #—]ús#   ”G# ÅH6Ç#H3È /H3È2H3È6I	c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r&   r  Úokr'   r  )r(   rß   s   "€r)   r*   r°  ï  s"   ø€ ÷ 8ñ 8¡Cð 8¹dð 8Átñ 8r+   c                ó²  € V P                  V4      pVf   \        V4      # VP                  '       d   RRRR/#  VP                  '       d   V! VP                  4       V# VP                  '       d   VP                  P
                  '       g   RRRR/# V! VP                  P
                  4       V#   \         d   pRRR\        T4      /u Rp?# Rp?ii ; i)u˜   Run a stdin operation on a running session â€” ``pty_op(pty)`` under PTY mode,
else ``pipe_op(stdin)`` on the Popen pipe â€” and return *ok* on success.Nr  r  r  zProcess has already finishedz?Process stdin not available (non-local backend or stdin closed))r†   r  r5  rŠ  rc  r�   r±   rf   )r>  r  Úpty_opÚpipe_opr'  r   rÌ  s   &&&&&  r)   Ú	_stdin_opÚProcessRegistry._stdin_opï  sÁ   € ð —(‘(˜:Ó&ˆØŠ?Ü˜jÓ)Ð)Ø�>�>ˆ>ØÐ.°Ð9WÐXÐXð		8Ø�|�|ˆ|Ù�w—|‘|Ô$ð
 ˆIð	 —_—_�_¨G¯O©O×,A×,AÐ,AØ  '¨7Ð4uÐvÐvá˜Ÿ™×-Ñ-Ô.ØˆIøÜô 	8Ø˜g w´°A³Ð7Õ7ûð	8ús;   ºB2 ÁB2 Á B2 Á2B2 ÂB2 ÂB2 Â2CÂ=CÃCÃCc                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# ©r&   r  Údatar'   r  )r(   rß   s   "€r)   r*   r°  	  s'   ø€ ÷ kñ k¡cð k±ð k¹ñ kr+   c                ó\   a€ V3R lpV3R lpV P                  WVRRR\        S4      /4      # )zASend raw data to a running process's stdin (no newline appended).c                 ó  <€ \         '       dD   T P                  \        S\        4      '       d   SP	                  R 4      M
\        S4      4       R# T P                  \        S\
        4      '       d   SP                  R R4      MS4       R# )r:   ÚsurrogateescapeN)rª  rJ  r~  rI  r°   rf   Úencode)rE  r/  s   &€r)   Úvia_ptyÚ,ProcessRegistry.write_stdin.<locals>.via_pty	  s[   ø€ ç‹{Ø—	‘	´*¸TÄ5×2IÒ2I˜$Ÿ+™+ gÔ.ÌsÐSWËyÖYð —	‘	ÄZÐPTÔVY×EZÒEZ˜$Ÿ+™+ gÐ/@ÔAÐ`dÖer+   c                 óJ   <€ V P                  S4       V P                  4        R # r  )rJ  rK  )r�   r/  s   &€r)   Úvia_pipeÚ-ProcessRegistry.write_stdin.<locals>.via_pipe	  s   ø€ Ø�K‰K˜ÔØ�K‰KŽMr+   r  r'  Úbytes_written)r+  r0  )r>  r  r/  r4  r7  s   &&f  r)   Úwrite_stdinÚProcessRegistry.write_stdin	  s3   ø€ õ	fõ	ð �~‰~˜j°8¸hÈÈoÔ_bÐcgÓ_hÐ=iÓjÐjr+   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# r.  r  )r(   rß   s   "€r)   r*   r°  	  s'   ø€ ÷ sñ s¡sð s±#ð s¹tñ sr+   c                ó¸   € V P                  V4      pT P                  Y\        '       d'   V'       d   VP                  '       d   R,           4      # R,           4      # )ul  Send data + newline to stdin (like pressing Enter).
On a Windows PTY, Enter is a carriage return: ConPTY treats ``\r`` as
end-of-line and a bare ``\n`` through pywinpty is NOT a line terminator â€” the
child's blocking line read (``readline()``, Go ``bufio.Scanner``) never returns
and the process hangs looking healthy. ``\r\n`` gives it both; POSIX keeps ``\n``.z
rÙ  )r†   r:  rª  rŠ  )r>  r  r/  r   s   &&& r)   Úsubmit_stdinÚProcessRegistry.submit_stdin	  sF   € ð —(‘(˜:Ó&ˆØ×Ñ 
¿k»kÏgÐZa×Zf×ZfÐZf°FÕ,qÓrÐrÐlpÕ,qÓrÐrr+   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r  )r(   rß   s   "€r)   r*   r°  	  s   ø€ ÷ .ñ .±ð .¹ñ .r+   c                óÌ   € V P                   f   RRRR/#  V P                  V P                  V4      V4       RRRTRR/#   \         d   pRRR\        T4      /u Rp?# Rp?ii ; i)	uÒ   Ask the desktop GUI to close this process's read-only terminal tab. Does NOT
kill the process â€” output keeps buffering and the tab can be reopened from the
status stack. Errors when no UI close sink is wired.Nr  r  z;close_terminal is only available in the Hermes desktop app.r'  Úclosedrç  z’Closed the read-only terminal tab. The process was not killed; its output remains available and the user can reopen the tab from the status stack.)r©  r†   r±   rf   )r>  r  rÌ  s   && r)   Úrequest_close_terminalÚ&ProcessRegistry.request_close_terminal	  s|   € ð �=‰=Ò Ø˜g wÐ0mÐnÐnð	8Ø�M‰M˜$Ÿ(™( :Ó.°
Ô;ð �d˜H jØð -ð.ð 	.øô ô 	8Ø˜g w´°A³Ð7Õ7ûð	8ús   –!? ¿A#Á
AÁA#ÁA#c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r  )r(   rß   s   "€r)   r*   r°  .	  s   ø€ ÷ rñ r¡cð r©dñ rr+   c           	     óŒ   € V P                  V4      pVe   VP                  '       d   RMRpV P                  VR R RRRV/4      # )zGClose a running process's stdin / send EOF without killing the process.zEOF sentzstdin closedc                 ó"   € V P                  4       # r  )ÚsendeofrD  s   &r)   r  Ú-ProcessRegistry.close_stdin.<locals>.<lambda>3	  s
   €  C§K¡K¤Mr+   c                 ó"   € V P                  4       # r  )rÅ  )r�   s   &r)   r  rI  3	  s
   € ÀÇÁÄr+   r  r'  r  )r†   rŠ  r+  )r>  r  r   r(  s   &&  r)   Úclose_stdinÚProcessRegistry.close_stdin.	  sO   € à—(‘(˜:Ó&ˆØ#Ò/°G·L·L°L‰jÀnˆØ�~‰~ØÑ1Ñ3NÐQYÐ[_ÐajÐloÐPpórð 	rr+   c                ó    <€ V ^8„  d   QhRS[ /# r%   r5   )r(   rß   s   "€r)   r*   r°  5	  s   ø€ ÷ "ñ "™sñ "r+   c                ó,   € \        V P                  4      # )zMO(1) running count for status-bar polling; dict ``len()`` is atomic, no lock.)r0  r™  r=  s   &r)   Úcount_runningÚProcessRegistry.count_running5	  s   € ä�4—=‘=Ó!Ð!r+   Úinclude_retainedc                óN   <€ V ^8„  d   QhRS[ R,          RS[ R,          RS[RS[/# )r&   r<  Nra  rQ  r'   )rf   rs   rg   )r(   rß   s   "€r)   r*   r°  9	  s=   ø€ ÷ @ñ @¡S¨4¥Zð @ÁSÈ4ÅZð @Ñmqð @ñ  Cñ @r+   c               óÖ  a € V'       d   \        4       M/ pS P                  ;_uu_ 4        VP                  S P                  4       VP                  S P                  4       RRR4       V 3R lVP                  4        4        Uu. uF$  pVf   K	  S P                  V4      '       d   K"  VNK&  	  ppV'       g	   V'       dH   V Uu. uF;  pV'       d   VP                  V8X  g   V'       g   K&  VP                  V8X  g   K9  VNK=  	  pp. pV EF:  pS P                  V4       RVP                  RVP                  R,          RVP                  RVP                  RVP                  R	\        P                  ! R
\        P                   ! VP"                  4      4      R\%        \        P                  ! 4       VP"                  ,
          4      RVP&                  '       d   RMRRVP(                  '       d   VP(                  RR MR/	p	V'       d0   V'       d(   VP                  V8w  d   VP                  V8X  d   RV	R&   VP*                  '       d   RV	R&   \,        V	R&   VP.                  '       dF   VP0                  '       g4   V	P                  \3        VP.                  4      VP4                  ^ 8„  R7       VP6                  '       d   RV	R&   VP8                  '       d   RV	R&   VP&                  '       d.   VP:                  V	R&   VP<                  V	R&   VP>                  V	R&   VP@                  '       d   RV	R&   VPC                  V	4       EK=  	  V#   + '       g   i     ELõ; iu upi u upi )uZ  Running and recently-finished processes for ``task_id`` and/or ``session_key``;
cross-task entries sharing the gateway session (a forgotten preview server
blocking session reset) are flagged ``"session_scoped": true``.

When ``task_id`` is given, processes that task spawned (its ``owner_task_id``) are included. When
``session_key`` is also given, session-scoped background processes (``background: true``) registered
under that gateway session are surfaced too, even if they belong to a different task â€” so the agent
can discover a forgotten preview server that is blocking session reset (#29177).
Nc              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5ir  )rJ  )r  r  r>  s   & €r)   r  Ú0ProcessRegistry.list_sessions.<locals>.<genexpr>J	  s#   øé € ð (Ù;L°a�×.Ñ.¨q×1Ð1Ó;Lùs   ƒ!r  rì   :NéÈ   Nre  rb  r;  rf  z%Y-%m-%dT%H:%M:%Srå  r  r5  r?  ræ  r9   TÚsession_scopedrl  Úwsl_note)ry  Ú	watch_hitrx  rn  r[  rh  rZ  ri  i8ÿÿÿ)"r   rF  rÌ  rš  r™  rÄ  rX  r;  ra  r‰  r`  rì   re  rb  r‘   ÚstrftimeÚ	localtimerf  r6   r5  r'  rl  Ú_WSL_CHAIN_NOTEry  r€  rg   r~  rx  rn  r[  rh  rZ  ri  rN   )
r>  r<  ra  rQ  Úsessionsru  Úall_sessionsr  r¶   Úentrys
   f&&$      r)   Úlist_sessionsÚProcessRegistry.list_sessions9	  s·  ø€ ÷ 0@Ô)Ô+ÀRˆØ�Z�Z‹ZØ�O‰O˜DŸN™NÔ+Ø�O‰O˜DŸM™MÔ*÷ ô(Ø;C¿?¹?Ô;Lô(ó
ñ(˜)àô à/3×/EÑ/EÀi×/P÷ ˆIñ (ð 	ð 
÷
 —ká'óÙ'�aß §¡°7Ô :Üô à$%§M¡M°[Ñ$@÷ �™<ð ð ð
 ˆÜˆAð ×&Ñ& qÔ)à˜aŸd™dØ˜1Ÿ9™9 T�?Ø�q—u‘uØ�q—u‘uØ §¡ØœdŸmšmÐ,?ÄÇÂÐPQ×P\ÑP\ÓA]Ó^Ø ¤#¤d§i¢i£k°A·L±LÕ&@Ó"AØ a§h§h h™(°IØ ¸A¿O¿O¸O !§/¡/°$°%Ñ"8ÐQSð
ˆE÷ Ÿ;¨1¯?©?¸gÔ+EÈ!Ï-É-Ð[fÔJfØ*.�Ð&Ñ'Ø�{�{ˆ{Ø%)��kÑ"Ü$3��jÑ!à××Ð¨×(9×(9Ð(9Ø—‘¬D°×1AÑ1AÓ,BÈaÏmÉmÐ^_ÑN_�Ô`Ø×#×#Ð#Ø.2�Ð*Ñ+Ø×#×#Ð#Ø.2�Ð*Ñ+Ø�x�xˆxØ%&§[¡[��kÑ"Ø%&§[¡[��kÑ"Ø-.×-@Ñ-@�Ð)Ñ*Ø�z�zˆzØ$(��jÑ!Ø�M‰M˜%× ñG ðH ˆ÷g �ZˆZüò
ùòs5   ª7MÂM!ÂM!Â)M!ÃM&ÃM&Ã-M&Ä M&ÍM	c                ó    <€ V ^8„  d   QhRS[ /# r%   r˜   )r(   rß   s   "€r)   r*   r°  }	  s   ø€ ÷ Vñ V©ñ Vr+   c                ó  a€ V P                   ;_uu_ 4        \        V P                  P                  4       4      pRRR4       X F  pV P	                  V4       K  	  V P                   ;_uu_ 4        \
        ;QJ d7    V3R lV P                  P                  4        4       F  '       g   K   RM,	  RM(! V3R lV P                  P                  4        4       4      uuRRR4       #   + '       g   i     L³; i  + '       g   i     R# ; i)z‘True if any still-running session satisfies *predicate*, after refreshing
detached sessions so a finished-but-unreaped process reads as inactive.Nc              3   ód   <"  € T F%  qP                   '       * ;'       d	    S! V4      x € K'  	  R # 5ir  )r5  )r  r  Ú	predicates   & €r)   r  Ú/ProcessRegistry._any_running.<locals>.<genexpr>…	  s&   øé € ÐUÑ>T¸Ÿ8™8”|×4Ð4©	°!«Ô4Ó>Tùs   ƒ0Ÿ0TF)rF  rg   r™  rÄ  rJ  r  )r>  re  r]  r   s   &f  r)   Ú_any_runningÚProcessRegistry._any_running}	  sœ   ø€ ð �Z�Z‹ZÜ˜DŸM™M×0Ñ0Ó2Ó3ˆH÷ ãˆGØ×*Ñ*¨7Ö3ñ  à�Z�Z‹Zß“3ÔU¸d¿m¹m×>RÑ>RÔ>TÓU—3—3’3ÔU¸d¿m¹m×>RÑ>RÔ>TÓUÓU÷ ŠZ÷	 �Zú÷ �ZˆZús   –$C%Á08C8Â+/C8Ã%C5	Ã8D		c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r&   r<  r'   rû   )r(   rß   s   "€r)   r*   r°  ‡	  s   ø€ ÷ Gñ G©Cð G±Dñ Gr+   c                ó.   a€ V P                  V3R l4      # )aN  Whether any process for ``task_id`` is still running. Ownership is
``owner_task_id`` (the raw spawning id) like the other task-scoped queries:
``task_id`` on a session is the collapsed container key, shared across
turns and delegate children, so a container-key match alone would miss a
delegate child's own background work (#120546).c                 ó"   <€ V P                   S8H  # r  )r;  )r  r<  s   &€r)   r  Ú6ProcessRegistry.has_active_processes.<locals>.<lambda>�	  s   ø€ ¨1¯?©?¸gÒ+Er+   ©rg  ©r>  r<  s   &fr)   Úhas_active_processesÚ$ProcessRegistry.has_active_processes‡	  s   ø€ ð × Ñ Ô!EÓFÐFr+   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# ©r&   r;  r'   ©rf   rg   r!  )r(   rß   s   "€r)   r*   r°  �	  s$   ø€ ÷ lñ l©cð l±d¹>Õ6Jñ lr+   c                ó  € V P                   ;_uu_ 4        V P                  P                  4        Uu. uF+  q"P                  V8X  g   K  VP                  '       d   K)  VNK-  	  upuuRRR4       # u upi   + '       g   i     R# ; i)z@Running processes whose RAW spawning owner is ``owner_task_id``.N)rF  r™  rÄ  r;  r5  ©r>  r;  r  s   && r)   Úrunning_owned_byÚ ProcessRegistry.running_owned_by�	  sV   € à�Z�Z‹ZØ#Ÿ}™}×3Ñ3Ô5ÓkÑ5˜!¿¹ÈMÑ9Y”AÐbc×bjÕbj—A�AÑ5Ñk÷ ŠZùÚk÷ �ZˆZús(   •A5²A0Á	A0ÁA0Á#A5Á0A5Á5B	c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rs  rt  )r(   rß   s   "€r)   r*   r°  ”	  s$   ø€ ÷ cñ c¹ð cÁÁnÕAUñ cr+   c                ó¨  € V P                   ;_uu_ 4        V P                  P                  4        Uu. uFv  pVP                  V8X  g   K  VP                  '       g   K*  VP
                  f   K:  VP                  V P                  9  g   KW  VP                  V P                  9  g   Kt  VNKx  	  upuuRRR4       # u upi   + '       g   i     R# ; i)zÐExited ``notify_on_complete`` processes of ``owner_task_id`` whose result nobody read (no wait/log/poll).
A child's completion notice is suppressed in the parent, so an unread exit is otherwise lost silently.N)	rF  rš  rÄ  r;  rx  r[  r`  r¡  r¢  rv  s   && r)   Úunread_completions_owned_byÚ+ProcessRegistry.unread_completions_owned_by”	  sª   € ð �Z�Z‹ZØ#Ÿ~™~×4Ñ4Ô6ó cÑ6˜!Ø—‘¨-Ñ7ô Ø<=×<PÕ<Pô àŸ™ô ð Ÿ™ D×$=Ñ$=Ñ=ô ð CDÇ$Á$Èd×NaÑNaÑBa÷ �AÑ6ñ c÷ ŠZùòc÷ �ZˆZús:   •C ²B;Á
B;ÁB;Á.B;ÂB;Â(B;Â.C Â;C Ã C	rç  c                óT   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RS[ RS[ RS[S[,          /# )r&   r  Ú
from_ownerÚto_ownerÚ
to_task_idÚto_session_keyrç  r'   rÅ  )r(   rß   s   "€r)   r*   r°  �	  sH   ø€ ÷ ñ ©Sð Áð ÑPSð Ñadð Ù+.ðÙ69ðÙCKÉNÕC[ñr+   c               ó"  € V P                  V4      pV P                  ;_uu_ 4        Ve$   VP                  '       g   VP                  V8w  d    RRR4       R# W7n        WGn        WWn        Wgn        VuuRRR4       #   + '       g   i     R# ; i)a‰  Move a RUNNING process from one owner to another under the registry lock. Ownership is the ``owner_task_id``
field: completion notices are stamped from it at exit time and teardown kills by it, so flipping it here is the
whole transfer. Returns the session, or None when it is unknown, already exited, or not owned by ``from_owner``
(the caller must not report a transfer that did not happen).N)r†   rF  r5  r;  r<  ra  rm  )r>  r  r~  r  r€  r�  rç  r   s   &&$$$$$ r)   Útransfer_ownershipÚ"ProcessRegistry.transfer_ownership�	  sg   € ð —(‘(˜:Ó&ˆØ�Z�Z‹ZØŠ '§.§. .°G×4IÑ4IÈZÔ4WØ÷ ‰Zð %-Ô!Ø(ŒOØ"0ÔØ#'Ô Ø÷ �Z�Z‹Zús   ¦A=½A=ÁA=Á=B	c                ó<   <€ V ^8„  d   QhRS[ RS[S[,          RS[/# )r&   ra  Úmax_active_ager'   )rf   r   rŒ  rs   )r(   rß   s   "€r)   r*   r°  ­	  s-   ø€ ÷ Sñ S±#ð SÁxÑPUÅð SÑbfñ Sr+   c                ó`   aaa€ \         P                   ! 4       oV P                  VVV3R l4      # )züActive processes for a gateway session key. Processes older than
``max_active_age`` seconds are ignored as stale so a forgotten ``http.server``
can't freeze session idle/daily reset forever; ``None`` keeps legacy behaviour
(any running process blocks).c                 óv   <€ V P                   S8H  ;'       d#    SR J ;'       g    SV P                  ,
          S8  # r  )ra  rf  )r  r†  rÆ  ra  s   &€€€r)   r  Ú8ProcessRegistry.has_active_for_session.<locals>.<lambda>´	  s>   ø€ �a—m‘m {Ñ2÷ Rð RØ 4Ð'×PÐP¨C°!·,±,Õ,>À.Ñ+PðRr+   )r‘   rg  )r>  ra  r†  rÆ  s   &ff@r)   Úhas_active_for_sessionÚ&ProcessRegistry.has_active_for_session­	  s+   ú€ ô
 �iŠi‹kˆØ× Ñ öRóSð 	Sr+   c                ó    <€ V ^8„  d   QhRS[ /# r%   r˜   )r(   rß   s   "€r)   r*   r°  ·	  s   ø€ ÷ 1ñ 1¡ñ 1r+   c                ó&   € V P                  R 4      # )uˆ   Whether ANY background process is running â€” scale-to-zero must not
suspend a gateway with live background work or the process is lost.c                 ó   € R # )Tr/   )r  s   &r)   r  Ú0ProcessRegistry.has_any_active.<locals>.<lambda>º	  s   € ©4r+   rn  r=  s   &r)   Úhas_any_activeÚProcessRegistry.has_any_active·	  s   € ð × Ñ ¡Ó0Ð0r+   c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# rj  )rf   Ú	frozenset)r(   rß   s   "€r)   r*   r°  ¼	  s#   ø€ ÷ Gñ G©Cð G±I¹cµNñ Gr+   c                óD   € \        R V P                  V4       4       4      # )ud  Running IDs owned by ``task_id`` â€” a turn-boundary marker: on timeout
only processes absent from the starting snapshot belong to the abandoned
turn; older ones intentionally span turns and must survive. Ownership is
``owner_task_id``: ``task_id`` is the container key (``session:<key>``,
``default``), shared across turns and sessions, not the turn's id.c              3   ó8   "  € T F  qP                   x € K  	  R # 5ir  râ  r€  s   & r)   r  Ú7ProcessRegistry.snapshot_running_ids.<locals>.<genexpr>Â	  s   é € ÐFÑ'E !ŸžÓ'Eùr‚  )r“  rw  ro  s   &&r)   Úsnapshot_running_idsÚ$ProcessRegistry.snapshot_running_ids¼	  s    € ô ÑF t×'<Ñ'<¸WÔ'EÓFÓFÐFr+   Úkill_allc                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r&   r<  rW  r'   )rf   r6   )r(   rß   s   "€r)   r*   r°  Ê	  s(   ø€ ÷ uñ u©#ð uÉð uÑPSñ ur+   c               óR   € T P                  T\        T;'       g    R4      VRR7      # )z¬Kill ``task_id`` processes created after ``baseline_ids``. Output is
consumed so an abandoned turn can't enqueue a follow-up reviving work the
timeout deliberately stopped.T)Úexclude_idsrW  r
  r/   )r™  r“  )r>  r<  Úbaseline_idsrW  s   &&&$r)   Úkill_started_sinceÚ"ProcessRegistry.kill_started_sinceÊ	  s*   € ð �}‰}˜W´)¸L×<NÐ<NÈBÓ2OÐX^Ðosˆ}ÓtÐtr+   rœ  c          
      óH   <€ V ^8„  d   QhRS[ S[,          RS[RS[RS[RS[/# )r&   r<  rœ  rW  r
  r'   )r   rf   r“  rs   r6   )r(   rß   s   "€r)   r*   r°  Ð	  s9   ø€ ÷ ñ Ù¡•}ðÙ=Fðáðá26ðáCFñr+   c          	     ón  € W0P                   9   pV P                  ;_uu_ 4        . V P                  P                  4       OV P                  P                  4       O Uu. uFq  pVe   VP
                  V8X  g   K  VP                  V9  g   K-  VP                  '       d   VP                  '       g   KS  V'       d   VP                  '       d   Ko  VNKs  	  ppRRR4       X Uu. uF  q`P                  VP                  W4R7      NK!  	  pp\        R V 4       4      # u upi   + '       g   i     LR; iu upi )aß  Kill all running processes, optionally only those ``task_id`` spawned (its ``owner_task_id``).
Returns how many it stopped. A session whose systemd scope did not stop is not counted
(its descendants may live on), and a later sweep retries it even after it finished.

Sessions with ``persist_on_release=True`` are skipped when ``source`` is an
agent-lifecycle sweep (the default ``kill_all`` release path, a gateway turn
timeout, or ``agent_close``): an explicitly persisted background job must survive
session end / compression / error recovery (#41225). An explicit operator stop
(``process.kill`` via process_manage, CLI /stop) passes its own source and still
reaches them, so the user can always stop a persisted process on purpose.N)rW  r
  c              3   ód   "  € T F&  pVP                  R 4      R9   ;'       d    RV9  x € K(  	  R# 5i)r  r  N>   rY  r  )r†   )r  Úrs   & r)   r  Ú+ProcessRegistry.kill_all.<locals>.<genexpr>æ	  s7   é € ð á�ð �E‰E�(‹OÐ;Ñ;×\Ð\Ð@SÐ[\Ñ@\Ô\Ûùs   ‚0¢0)Ú_LIFECYCLE_KILL_SOURCESrF  r™  rÄ  rš  r;  r`  r5  r†  rn  r  Úsum)	r>  r<  rœ  rW  r
  Ú	lifecycler  Útargetsr¾  s	   &&$$$    r)   r™  ÚProcessRegistry.kill_allÐ	  s  € ð ×:Ñ:Ñ:ˆ	Ø�Z�Z‹ZàN˜TŸ]™]×1Ñ1Ó3ÐN°d·n±n×6KÑ6KÓ6MÑNóÙN�aØ’O q§¡¸'Ñ'Aô à—D‘D Ñ+ô à56·X·X°XÀ×AVÕAVô ÷ # q×';Õ';÷ �ÑNð ð ÷ ñ cjÓjÑbiÐ]^×$Ñ$ Q§T¡T°&Ð$ÖXÑbiˆÐjÜñ áóó ð 	ùò÷ �Züò ksG   £9DÁDÁ8DÂDÂDÂ1DÂ9DÃDÃDÃ!%D2ÄDÄD/	c           	     óê  a € ^ RI Hp \        P                  ! 4       pS P                  P	                  4        UUu/ uF,  w  r4\        VRR4      '       d   K  V! V4      '       d   K*  W4bK.  	  pppVP	                  4        UUu. uF$  w  r4W$P                  ,
          \        8”  g   K"  VNK&  	  ppp\        S P                  4      \        S P                  4      ,           \        V4      ,
          \        8¬  pV'       dC   V Uu. uF  q3V9  g   K  VNK  	  up;p'       d!   VP                  \        VV 3R lR7      4       V F2  pS P                  S P                  V,          4       S P                  V K4  	  S P                  P                  4       S P                  P                  4       ,          p	S ;P                  V	,          un        S ;P                   V	,          un        R# u uppi u uppi u upi )ztDrop expired, then oldest-over-cap finished sessions (hold _lock); keep pending scope stops and unpublished notices.)Úretained_for_deliveryr†  Fc                 ó>   <€ SP                   V ,          P                  # r  )rš  rf  )rÑ  r>  s   &€r)   r  Ú2ProcessRegistry._prune_if_needed.<locals>.<lambda>õ	  s   ø€ ¸$¿.¹.ÈÕ:M×:XÒ:Xr+   )r  N)Útools.process_registry_awaitingr«  r‘   rš  rÍ  r  rf  ÚFINISHED_TTL_SECONDSr0  r™  ÚMAX_PROCESSESrN   rQ   r_  Úkeysr¡  r¢  )
r>  r«  rÆ  rÑ  r  ÚprunableÚexpiredÚover_capr  Útrackeds
   f         r)   r™  Ú ProcessRegistry._prune_if_neededì	  sr  ø€ åIÜ�iŠi‹kˆØ)-¯©×)=Ñ)=Ô)?ô fÑ)?™v˜sÜ" 1Ð&;¸U×Cô ÙLaÐbc×Ldô �C’FÑ)?ˆñ fà%-§^¡^Ô%5ÔeÑ%5™6˜3¸#ÇÁÕ:LÔPdÑ9d—3�3Ñ%5ˆÑeÜ�t—}‘}Ó%¬¨D¯N©NÓ(;Õ;¼cÀ'»lÕJÌmÑ[ˆß±hÓ&U±h¨sÈWÑBT§s s±hÑ&UÐU˜ÖUØ�N‰Nœ3˜yÔ.XÔYÔZÛˆCð ×*Ñ*¨4¯>©>¸#Õ+>Ô?Ø—‘˜sÒ#ñ ð —-‘-×$Ñ$Ó&¨¯©×)<Ñ)<Ó)>Õ>ˆØ×!Ò! WÕ,Õ!Ø×Ò˜wÕ&×ùó'fùãeùâ&Us)   ºG$ÁG$Á&G$ÂG*Â&G*ÄG0ÄG0)r¡  r²  rš  r£  r§  r¥  r¦  r¤  rª  rF  r¢  r™  rž  r©  r¨  r›  )zno job control in this shellz!cannot set terminal process groupz)tcsetattr: Inappropriate ioctl for device)r/   )Nr9   r9   NFr9   F)Nr9   r9   é
   r9   Fr‘  r  )r9   N)NrV  )r9   )NN>   r™  Úagent_closeÚgateway_turn_timeout)brË   rÌ   rÍ   rÎ   rÏ   rß  r²  r­  r´  r³  r½  rÅ  Ústaticmethodrá  rè  r  rù  rÑ  r  rü  r/  r4  Úclassmethodr;  rC  rJ  rH  rG  rX  rc  rh  ro  rx  r‚  r‰  r‘  r�  r´  rÐ  rÈ  rÛ  ró  rÇ  r  r!   r*  rí  r¯  rû  r!  rT  rY  r`  r_  rm  rq  rv  r‘  r†  rš  r   r«  rµ  rÂ  rË  r†   rÇ  r‰  rà  r  rö  rÖ  r   r  r  r  r+  r:  r>  rC  rK  rO  r`  rg  rp  rw  r{  rƒ  rŠ  r�  r—  r“  r¥  rž  r™  r™  rÐ   râ   rã   s   @r)   r—  r—  ¢  s  ø‡ € ñQð5Ðð
 "Ðò$B÷N	ð 	÷+ð +÷3ð 3÷0ð 0ð4 ÷ ó ð ÷!ð !÷Hð H÷T
ð 
ð ÷
ó ð
ð ÷
ó ð
÷(ð (ðT ÷ ó ð ð ÷ó ðð ÷Xó ðX÷ð ÷(ð ÷ (ð (÷$9ð 9÷$:ð :ð ÷Dó ðDð ÷ó ðð ÷Qó ðQð ÷-ó ð-ð ÷
%ó ð
%÷ð ð& ÷ó ð÷!ò !÷ ð ÷.Aò A÷F!ð !ðØZ\ðàðà46ðàMOðð $(÷ò ÷&ò ÷@XJð XJ÷t2ð 2ñ. &Ð&7Ó8Ð÷:ð :÷x4Tð 4Tðl)ÐZ_÷ )ò )÷(ò (÷ð ÷B4ð 4ð, ÷
ó ð
÷%ð %ðF ÷>ó ð>÷7ð 7÷`ð `ñ"QØHLðQØeh÷Qó Qðf ÷Yó ðYð	uÐPT÷ 	uò 	uð ÷ó ðð ÷Aó ðA÷.ð .ñ,5ØTX÷5ó 5ðp Ð÷	tð 	t÷Kð K÷$I(ð I(ðV ÷{ó ð{÷ð ÷4ò ÷<Eò EðN ÷Tó ðTð^8Ø0>ð^8ØW[÷^8ò ^8ð@ ÷ó ð÷2ð 2÷h8ð 8÷&kð k÷"sò s÷.ð .÷$rð r÷"ð "ñ@Ðty÷ @ó @÷HVð V÷Gð G÷lð l÷
cð cðØ<>÷ò ÷ Sò S÷1ð 1÷
Gð Gñ (Ò([Ó\Ð÷uð uñÙIRËðà ðà9>÷ó ÷8'ð 'r+   r—  )ÚregistryÚ
tool_errorrº  Úprocess_manageÚdescriptionu  Poll, wait on, or kill background terminal processes (from terminal(background=true)). Completed results remain retrievable by session_id when resuming their owning conversation (up to 7 days, newest 64 results per profile; rolling output tail). poll: status + new output. log: full output, paged. wait: block until exit or timeout (partial output on timeout). write vs submit: submit appends Enter â€” use it to answer prompts; write sends raw bytes, no newline. close: EOF stdin. kill: terminate. handoff (subagents only): transfer a running process you started to your parent agent, which then receives its completion; `data` = one sentence on its purpose. Subagent-owned processes are otherwise killed when the subagent finishes and their notifications never reach the parent.Ú
parametersrË  ÚobjectÚ
propertiesÚactionÚstringÚenumr  rË  rÖ  r"  rJ  ÚsubmitrÅ  r  ztFrom terminal background output; any unique prefix works ('4dae' for proc_4dae56ca81f6). Required except for 'list'.r/  z:Stdin text for write/submit; purpose sentence for handoff.rŸ   ÚintegerzMax seconds for 'wait'.Úminimumrì  z$Log line offset (default: last 200).r1  zMax log lines.Úrequiredr9   c          
      ój   € V ^8„  d   QhR\         R\         R\        \        ,          R\         R\         /# )r&   r,  rì   r­   r<  r'   )rf   r   r6   )r(   s   "r)   r*   r*   C
  s=   € ÷ Xñ X¤Sð X´cð XÄxÔPSÅ}ð XÔ_bð XÔloñ Xr+   c               ó6   € ^ RI Hp T! YY#;'       g    RR4      # )u
  ``transform_terminal_output`` seam for background-process output â€” the poll/wait/log/kill
results and the completion/heartbeat/watch notifications â€” so a plugin that rewrites terminal
output sees the same command output whether it ran in the foreground or not (#70760).
Same helper as the foreground path; callers redact AFTER it, never before, so a replacement
the plugin returns is still masked. ``returncode`` is None while the process is running and
``env_type`` is not recorded per process, so it is passed empty.)Ú_apply_output_transform_hookr9   )Útools.terminal_tool_resultrÌ  )r,  rì   r­   r<  rÌ  s   &$$$ r)   Útransform_process_outputrÎ  C
  s   € õ HÙ'¨¸Ç]À]ÐPRÐTVÓWÐWr+   c                ó0   € V ^8„  d   QhR\         R\         /# )r&   r¶   r'   r*  )r(   s   "r)   r*   r*   N
  s   € ÷ ñ ¤4ð ¬Dñ r+   c                ó¦  € \        V \        4      '       g   V # ^ RIHpHp V P                  R4      ;'       g    Rp\        V P                  R4      ;'       g    R4      pV'       g\   \        P                  \        V P                  R4      ;'       g    R4      4      ;pe!   \        \        VRR4      ;'       g    R4      pR
 F]  p\        V P                  V4      ;p\        4      '       g   K,  V'       g   K6  \        WsV P                  R4      VR7      pV! Ws4      W&   K_  	  \        V\        4      '       d   V'       d   V! VRR	7      V R&   V # )a°  Transform, then redact secrets from background-process output before it reaches the
model, session.db and CLI, mirroring the foreground ``terminal`` pipeline (hook first,
redaction after) so the two surfaces can't diverge. Respects ``security.redact_secrets``;
``redact_terminal_output`` picks ``code_file`` from the recorded command.

The command string itself is also redacted in case it carried an inline credential. See #43025.
)Úredact_sensitive_textÚredact_terminal_outputrì   r9   r<  r  r[  )rì   r­   r<  T)Ú	code_file)r,  ræ  )
r~  r   Úagent.redactrÑ  rÒ  r†   rf   Úprocess_registryr  rÎ  )r¶   rÑ  rÒ  rì   r<  r   r  Úvalues   &       r)   rÒ  rÒ  N
  s  € ô �fœd×#Ò#ØˆßJà�j‰j˜Ó#×)Ð) r€Gä�&—*‘*˜YÓ'×-Ð-¨2Ó.€GßÔ#3×#7Ñ#7¼¸F¿J¹JÀ|Ó<T×<ZÐ<ZÐXZÓ8[Ó#\Ð\˜ÒiÜ”g˜g y°"Ó5×;Ð;¸Ó<ˆÛ+ˆÜ˜vŸz™z¨#›Ð.�e´×4Ô4¿¹Ü,¨UÐPV×PZÑPZÐ[fÓPgÐqxÔyˆEÙ0°Ó@ˆF‹Kñ ,ô �'œ3×Ò§GÙ1°'ÀTÔJˆˆyÑØ€Mr+   c                ó$   € V ^8„  d   QhR\         /# r%   r*  )r(   s   "r)   r*   r*   h
  s   € ÷ Wñ W¤ñ Wr+   c                 ó   € R p\        \        4      ;_uu_ 4        ^ RIHp V! R R7      ;'       g    R pRRR4       R\        P                  Y;'       g    RRR7       Uu. uF  p\        V4      NK  	  up/#   + '       g   i     LL; iu upi )r9   )Úget_current_session_key)r8  NÚ	processesT)r<  ra  rQ  )r   r±   Útools.approval_contextrÙ  rÕ  r`  rÒ  )r<  ra  rÙ  rï  s   &   r)   Ú_list_processesrÜ  h
  s“   € ð €KÜ	”)×	Õ	åBÙ-°bÔ9×?Ð?¸Rˆ÷ 
ð ä!×/Ñ/Ø×)<Ð)<¸Ètð 0ô UóVñUˆAô 	˜qÖ!ñUñVð Wð W÷	 
×	üòVs   šA8Á BÁ8B	c                 ó,   € \         P                  V 4      # r  )rÕ  r  ©rÑ  Úas   &&r)   r  r  y
  s   € Ô,×1Ñ1°#Ô6r+   c                 ón   € \         P                  WP                  R 4      VP                  R^È4      R7      # )rì  r1  )rì  r1  )rÕ  rö  r†   rÞ  s   &&r)   r  r  z
  s-   € Ô+×4Ñ4°SÇÁÀxÃÐXY×X]ÑX]Ð^eÐgjÓXkÐ4Ôlr+   c                 óL   € \         P                  WP                  R 4      R7      # )rŸ   rÔ  )rÕ  rÖ  r†   rÞ  s   &&r)   r  r  {
  s   € Ô,×1Ñ1°#¿u¹uÀYÓ?OÐ1ÔPr+   c                 ó,   € \         P                  V 4      # r  )rÕ  r  rÞ  s   &&r)   r  r  |
  s   € Ô,×9Ñ9¸#Ô>r+   c           	      ó`   € \         P                  V \        VP                  R R4      4      4      # ©r/  r9   )rÕ  r:  rf   r†   rÞ  s   &&r)   r  r  }
  s#   € Ô-×9Ñ9¸#¼sÀ1Ç5Á5ÈÐQSÓCTÓ?UÔVr+   c           	      ó`   € \         P                  V \        VP                  R R4      4      4      # rä  )rÕ  r>  rf   r†   rÞ  s   &&r)   r  r  ~
  s#   € Ô.×;Ñ;¸CÄÀQÇUÁUÈ6ÐSUÓEVÓAWÔXr+   c                 ó,   € \         P                  V 4      # r  )rÕ  rK  rÞ  s   &&r)   r  r  
  s   € Ô-×9Ñ9¸#Ô>r+   c                ó^   € V ^8„  d   QhR\         R\        R\        \         ,          R\        /# )r&   r  r—  r<  r'   )rf   r   r   )r(   s   "r)   r*   r*   ƒ
  s,   € ÷ #-ñ #-¤ð #-¬Dð #-¼8ÄC½=ð #-ÌTñ #-r+   c                ó  € ^ RI HpHp ^ RIHp T;_uu_ 4        TP                  \        T;'       g    R4      4      pRRR4       X'       d   VP                  R4      MRp\        VRR4      p\        V4      '       d   V! 4       MRp	V	f   RR/# \        \        V	R	R4      ;'       g    \        V	R
R4      ;'       g    R4      p
V
'       g   RR/# \        VRR4      pVf	   . ;q·n	        \        V4      \        8¼  d   RR\         R2/# \        VP                  R4      ;'       g    R4      P                  4       pV'       g   RR/# \        P                  T \        T;'       g    R4      T
V! V
4      \        \        V	R
R4      ;'       g    R4      VR7      pVf	   RRV  R2/# VP                  R
VP                   RVP"                  RV/4       RRR
VP                   RVP"                  RR/#   + '       g   i     ELº; i)a•  Subagent-only: transfer a running background process to the parent agent so its completion is delivered THERE
(child-owned process notices are suppressed and child teardown kills what it owns). Validated against the live spawn
tree: the caller must be a registered child and must own the process; anything else is an error, never a silent
no-op, so a PID mentioned in prose can't masquerade as a transfer.)Ú_active_subagentsÚ_active_subagents_lock)Ú_resolve_container_task_idr9   NÚagentÚ_delegate_parent_refr  zThandoff is only available to a running subagent with a live parent; you are not one.Ú_current_task_idr  zNparent has no process owner id yet; retry after the parent's turn has started.Ú_handed_off_processeszhandoff cap reached (z2 per subagent); wait on or kill the rest yourself.r/  zshandoff requires `data`: one sentence saying what the process is for and what the parent should do with its result.)r~  r  r€  r�  rç  zcannot hand off zf: not a running process you own (already exited? read its result with poll/log and report it instead).rì   rç  r  Ú
handed_offzzYour parent now owns this process and will receive its completion; you will not. Mention the handoff in your final answer.)Útools.delegate_tool_registryré  rê  Útools.terminal_toolrë  r†   rf   r  r}  rï  r0  Ú_MAX_HANDOFFS_PER_CHILDrC   rÕ  rƒ  rN   r`  rì   )r  r—  r<  ré  rê  rë  ÚrecordÚchildÚ
parent_refÚparentÚparent_ownerÚhandedrç  r   s   &&&           r)   Ú_handoff_processrú  ƒ
  sþ  € ÷
 WÝ>ß	Ò	Ø"×&Ñ&¤s¨7¯=¨=°bÓ'9Ó:ˆ÷ 
 ç#)ˆF�J‰J�wÔ¨t€EÜ˜Ð 6¸Ó=€JÜ% j×1Ò1‰ZŒ\°t€FØ‚~ØÐoÐpÐpÜ”w˜vÐ'9¸2Ó>×iÐiÄ'È&ÐR^Ð`bÓBc×iÐiÐgiÓj€LßØÐiÐjÐjÜ�UÐ3°TÓ:€FØ‚~Ø/1Ð1ˆÔ,Ü
ˆ6ƒ{Ô-Ô-ØÐ0Ô1HÐ0IÐI{Ð|Ð}Ð}Üˆt�x‰x˜Ó×%Ð% 2Ó&×,Ñ,Ó.€DßØð  Oð  Pð  	PÜ×1Ñ1Øœs 7§= =¨bÓ1¸LÙ-¨lÓ;Üœ7 6¨<¸Ó<×BÐBÀÓCÈ$ð 2ó P€Gð ‚ØÐ+¨J¨<ð 8Að Að Bð 	Bà
‡M�M�< §¡¨Y¸¿¹ÈÐQUÐVÔWØ�l L°'·*±*¸iÈÏÉØð ,ð-ð -÷5 
 ×	Ð	ús   ™%G/Ç/H 	c           	      ó”  € V P                  R R4      pV P                  R4      e   \        V P                  RR4      4      MRpVR8X  d1   \        P                  ! \	        VP                  R4      4      RR7      # VR8X  dE   V'       g   \        R4      # \        P                  ! \        W0VP                  R4      4      RR7      # V\        9   dl   V'       g   \        R	V 24      # \        V,          w  rE^ R
IH	p V! W#V! W04      4      p\        P                  ! V'       d   \        V4      RR7      # TRR7      # \        RV R24      # )rÃ  r9   r  rg   r<  F)Úensure_asciiÚhandoffz"session_id is required for handoffzsession_id is required for )Úapply_wait_poll_policyzUnknown process action: zA. Use: list, poll, log, wait, kill, write, submit, close, handoff)r†   rf   ÚjsonÚdumpsrÜ  r½  rú  Ú_SESSION_ACTIONSÚ"tools.process_registry_wait_policyrþ  rÒ  )r—  ÚkwrÃ  r  ÚhandlerÚredactrþ  r¶   s   &,      r)   Ú_handle_processr  ¬
  s  € Ø�X‰X�h Ó#€Fà48·H±H¸\Ó4JÒ4V”�T—X‘X˜l¨BÓ/Ô0Ð\^€JØ�ÔÜ�zŠzœ/¨"¯&©&°Ó*;Ó<È5ÔQÐQØ�ÔßÜÐBÓCÐCÜ�zŠzÔ*¨:¸R¿V¹VÀIÓ=NÓOÐ^cÔdÐdØÔ!Ô!ßÜÐ ;¸F¸8ÐDÓEÐEÜ*¨6Õ2‰ˆÝMÙ'¨¹GÀJÓ<UÓVˆÜ�zŠz¿FÔ0°Ó8Ð]bÔcÐcÈÐ]bÔcÐcÜÐ0°°Ð8yÐzÓ{Ð{r+   rg  u   âš™ï¸�)rº  ÚtoolsetÚschemar  Úemojic                óV   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   # )r&   r�   )Ú__conditional_annotations__r   rs   )r(   s   "r)   r*   r*      s$   € ÷ ñ ÷\ 0Ò /œ(¤4�.Ñ /ò]r+   r@   i   i   @l        r  )r  r  r  r  r  Ú
message_id)rì   rb  rj  rg  rk  rl  re  rf  r<  r;  ra  )	rg   r  rË  rÖ  r"  rJ  rÆ  rÅ  rý  )Šr  rÏ   r  Ú
contextlibr   rÿ  ÚloggingrA   r  ré  r#  rw   rª   r  r�  r‘   r¦   Úpathlibr   Úsystemrª  r…   Útools.environments.localr   r   r	   r
   Úhermes_cli._subprocess_compatr   Údataclassesr   r   Útypingr   r   r   r   r   r   r`  r   Ú$tools.process_registry_notificationsr   r   r   r   Ú!tools.process_registry_checkpointr   Ú!tools.process_registry_output_logr   r   r   r   Ú"tools.process_registry_terminationr   Útools.process_registry_resultsr   r    Útools.process_registry_env_logr!   Útools.process_registry_wslr"   Ú	getLoggerrË   rF   r-   r.   r0   r’  r/  r¯  r°  rú  rø  rû  r²  rÃ  r  rÕ  r$  r#  r%  r�   r�  r¢   r“   r”   rj   rE   rU   rR   ra   rl   rp   r|   r�   r–   r¸   rÂ   rÈ   rÖ   rÂ  rÊ   r×   ró   rô   rÙ   ré   rù   r	  r  r  r(  r3  r!  r  Ú_CHECKPOINT_FIELDSÚ__dataclass_fields__rÄ  rº  r8  Ú_CHECKPOINT_DEFAULTSr\  r—  rÕ  Útools.registryr¼  r½  ÚPROCESS_SCHEMArÎ  rÒ  rÜ  r  rú  ró  r  Úregisterr*   )Úfr  s   0@r)   Ú<module>r$     sŠ  øðöó Ý Û Û Û 	Û Û Û Û Û Û Û Û Û Ý à�oŠoÓ 9Ñ,€ð �OŠOÓ Ñ(€	ß lÓ lÝ <ß (ß A× Aå -÷tó tå Dß |Ó |Ý Fß XÝ <Ý ?à	×	Ò	˜8Ó	$€ñ "Ó#Ð&6Õ6€Ø,Ð õvð Ð ð Ð ØÐ Ø€ð  Ð ØÐ ð Ð ð Ð ØÐ ð !Ð Ø#&Ð  ð !Ð Ø Ð Ø "Ð ð ,0Ð Ó /Ø%ŸNšNÓ,Ð ØÐ ð $(Ð  ð Ð Ø/Ð Ø#5Ð  Ø5Ð õ3Mõlõ,õ
÷"õJ7õ2õjõ(Tð  Ð ô ,ô õ2ðRð ð$ð ô˜:ô õð*52à!÷52õp õFõPõ2õ`ð ÷i1ð i1ó ði1ðZ aÐ ò=ñ 3Ñ1Ó2ð=ð 5Gð=ð ð	=ð .ð	=ð 0Ið	=ð K[ð	=ð
 ð=ð
 .ð=ð
 0<ñ=Ð ð ×0Ñ0×7Ñ7Ô9óá9ˆØ‡v�vÐ#Ñ#ô =€A‡F�F�1—6‘6Ð-Ô-‰R°1·9±9Ò<Ù9ñÐ ð,ð ôa'Ð-Ð/EÐG\ô a'ñL; #Ó$Ð ÷ 0ð Ðð ð
	\ð Ø�ØØØ˜ØÒfðð Ø˜Øð   Vðð Ø˜ØÐ[ðð Ø˜	ØÐ8Ø˜1ðð
 Ø˜	ØÐEðð Ø˜	ØÐ/Ø˜1ðð-
ð8 	�X�Jð=ð%2€ðjXÐeg÷ Xõõ4Wð" Ñ6¸Ð=Ø	ÑlÐnrÐsØ
ÑPÐRVÐWØ
Ñ>ÀÐEØÑVÐX]Ð^ØÑXÐZ_Ð`ØÑ>ÀÐFðÐ õ#-ðL Ð ò|ð( 	× Ó Ø	ØØØØ
÷ùòYAs   ÈLÈ+.L