+
    lHàj³ ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHtHtHt ^ RIHt ^ RIHt ^ RIHtHtHt ^ RIHtHt ^ R	IHtHtHtHtHtH t H!t!H"t"H#t#H$t$H%t%H&t&H't'H(t(H)t) ]PT                  ! ]+4      t,^2t-^Èt.R
 R lt/R R lt0R R lt1R R lt2R R lt3]R R l4       t4]R R l4       t5]6! 0 RÄm4      t7 ! R R]84      t9R R  lt:R!]6! R"R#04      R$]6! R%04      /t;R&]<R'&   R( R) lt=R* R+ lt>R, R- lt?R. R/ lt@R0 R1 ltAR2 R3 ltBR4 R5 ltCR6 R7 ltDR8 R9 ltER: R; ltFR< R= ltG]
R>R?/R@ RA ll4       tHRB RC ltIRD RE ltJRF RG ltKRH RI ltLRJ RK ltMRL RM ltNRNR?/RO RP lltORQ RR ltPRS RT ltQRÅRU RV lltRRWRXRYRXRZRXR[R?R\R?R]R?/tSR^ R_ ltTRÅR` Ra lltU]V! RbP¯                  4       4      tX]V! RcP¯                  4       4      tY]V! RdP¯                  4       4      tZRÆt[RÇt\]V! ReP¯                  4       4      t]RÈt^Rf Rg lt_Rh Ri lt`]6! RjRk04      taRl Rm ltbRRnRoRpRq/RRnRrRpRs//tcRt Ru ltdRvteRwsfRx]<Ry&   R?sgRz R{ lthR| R} ltiR~tjRwskRx]<R&   / tlR€]<R�&   R‚ Rƒ ltm]>! R„4      R… R† l4       tn]>! R‡4      Rˆ R‰ l4       to]>! R4      RŠ R‹ l4       tp]>! R4      RŒ R� l4       tq]>! R4      RŽ R� l4       tr]>! R4      R� R‘ l4       ts]>! R4      R’ R“ l4       tt]>! R”4      R• R– l4       tu]>! R—4      R˜ R™ l4       tvRš R› ltw]>! Rœ4      R� Rž l4       tx^tyRŸ R  ltz]>! R$4      R¡ R¢ l4       t{]>! R£4      R¤ R¥ l4       t|R¦ R§ lt}]>! R!4      R¨ R© l4       t~Rª R« ltR¬ R­ lt€R® R¯ lt�]>! R°4      R± R² l4       t‚]>! R³4      R´ Rµ l4       tƒ]6! R‡R°04      t„R„](]nR¶3R‡]$]oR¶3R] ]pR·3R]]qR¸3R]']rR¹3R]&]sRº3R]%]tR»3R”]"]uR¼3R—]]vR½3Rœ]]xR¾3R$]]{R¾3R£]]|R¾3R!]!]~R¿3R°])]‚RÀ3R³]#]ƒRÁ33t…]… F,  w  t†t‡tˆt‰]†]„9   d   ]5M]4tŠ]EP                  ! ]†RÂ]‡]ˆ]‰]ŠRÃ7       K.  	  R# )Éu«  Kanban tools â€” structured tool-call surface for worker + orchestrator agents.

Registered only under the dispatcher (``HERMES_KANBAN_TASK`` set) or when the profile
enables the ``kanban`` toolset. Tools rather than ``hermes kanban`` shell-outs: they run
in the agent's process (reach ``kanban.db`` from a container/SSH terminal backend, no
shlex quoting of JSON metadata, structured-JSON failures). Humans use CLI/dashboard.
)ÚannotationsN)Úcontextmanager)ÚAnyÚCallableÚOptional)Úredact_sensitive_text)Ú
judge_goal)Úno_cache_check_fnÚregistryÚ
tool_error)Úcfg_getÚload_config)ÚKANBAN_ATTACH_SCHEMAÚKANBAN_ATTACH_URL_SCHEMAÚKANBAN_ATTACHMENTS_SCHEMAÚKANBAN_BLOCK_SCHEMAÚKANBAN_COMMENT_SCHEMAÚKANBAN_COMPLETE_SCHEMAÚKANBAN_CREATE_SCHEMAÚKANBAN_HEARTBEAT_SCHEMAÚKANBAN_LINK_SCHEMAÚKANBAN_LIST_SCHEMAÚKANBAN_REQUEST_CHANGES_SCHEMAÚKANBAN_REQUEST_REVIEW_SCHEMAÚKANBAN_SCHEDULE_SCHEMAÚKANBAN_SHOW_SCHEMAÚKANBAN_UNBLOCK_SCHEMAc               ó   € V ^8„  d   QhRR/# ©é   ÚreturnÚbool© )Úformats   "Ú7/home/ubuntu/.hermes/hermes-agent/tools/kanban_tools.pyÚ__annotate__r%   %   s   € ÷ ñ  Tñ ó    c                 ó°  aa€ ^ RI Hp  V ! 4       pV'       d   R#  \        4       oRSP                  R4      ;'       g    . 9   d   R# Ve   R# ^ RIHo SP                  R4      ;'       g    / p\        ;QJ d.    VV3R lVP                  4        4       F  '       g   K   R# 	  R# ! VV3R lVP                  4        4       4      #   \         d     R# i ; i)	é    )Úkanban_toolset_requestedTÚkanbanÚtoolsetsF)Ú_get_platform_toolsÚplatform_toolsetsc              3  ót   <"  € T F-  w  r\        V\        4      '       g   K  R S! SVRR7      9   x € K/  	  R# 5i)r*   F)Úinclude_default_mcp_serversN)Ú
isinstanceÚlist)Ú.0ÚplatformÚnamesr,   Úconfigs   &  €€r$   Ú	<genexpr>Ú._profile_has_kanban_toolset.<locals>.<genexpr>8   s6   øé € ð 
á#4‘�¼
À5Ì$×8Oô aˆHÑ+¨F°HÐZ_Ô`Ö`Û#4ùs   ƒ8¢8)	Útools.kanban_toolset_contextr)   r   ÚgetÚhermes_cli.tools_configr,   ÚanyÚitemsÚ	Exception)r)   Ú	requestedÚ	platformsr,   r5   s      @@r$   Ú_profile_has_kanban_toolsetr@   %   s¿   ù€ ÝEá(Ó*€IßÙðÜ“ˆà˜Ÿ
™
 :Ó.×4Ð4°"Ô5ÙØÒ áõ 	@à—J‘JÐ2Ó3×9Ð9°rˆ	ß‹sõ 
à#,§?¡?Ô#4ó
�sŒsð 	
Šsð 	
ˆsõ 
à#,§?¡?Ô#4ó
ó 
ð 	
øô ô Úðús@   ›"C ¾C ÁC ÁC Á+C Á9#C ÂC Â"C Â&C ÃCÃCc               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú	predicateÚstrÚdefaultr!   r    r"   )r#   s   "r$   r%   r%   @   s!   € ÷ ñ ˜sð ¨Tð °dñ r&   c                óV   €  ^ RI Hp \        W 4      ! 4       #   \         d    Tu # i ; i)zT``agent.delegation_context.<predicate>()``; ``default`` when it cannot be evaluated.)Údelegation_context)ÚagentrF   Úgetattrr=   )rB   rD   rF   s   && r$   Ú_delegation_ctxrI   @   s-   € ðÝ,ÜÐ)Ô5Ó7Ð7øÜô ØŠðús   ‚ ˜(§(c               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   I   s   € ÷ @ñ @ Tñ @r&   c                 ó   € \        R R4      # )Úis_delegated_child_contextF©rI   r"   r&   r$   Ú_is_delegated_child_contextrN   I   s   € ÜÐ7¸Ó?Ð?r&   c               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   M   s   € ÷ Gñ G Tñ Gr&   c                 ó   € \        RR4      # )uŒ   False for delegate_task children AND for cron jobs fired in-process from
a worker â€” i.e. whenever HERMES_KANBAN_* is present but not ours.Ú"is_dispatcher_owned_worker_contextTrM   r"   r&   r$   Ú_is_dispatcher_owned_workerrR   M   s   € ô Ð?ÀÓFÐFr&   c               ó    € V ^8„  d   QhRRRR/# )r   Úto_env_workerr!   r    r"   )r#   s   "r$   r%   r%   S   s   € ÷ )ñ )˜tð )¨ñ )r&   c                ó¨   € \        4       '       d   R# \        P                  P                  R4      '       d   \	        4       '       d   V # \        4       # )z‹check_fn core: never for delegate children; dispatcher-spawned env workers
(HERMES_KANBAN_TASK) per flag; else the profile toolset decides.FÚHERMES_KANBAN_TASK)rN   ÚosÚenvironr9   rR   r@   ©rT   s   $r$   Ú_visiblerZ   S   s<   € ô #×$Ò$ÙÜ	‡z�z‡~�~Ð*×+Ò+Ô0K×0MÒ0MØÐÜ&Ó(Ð(r&   c               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   ^   s   € ÷ (ñ (˜Dñ (r&   c                 ó   € \        RR7      # )zKLifecycle tools: dispatcher workers + profiles with the ``kanban`` toolset.TrY   ©rZ   r"   r&   r$   Ú_check_kanban_moder^   ]   s   € ô  $Ô'Ð'r&   c               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   d   s   € ÷ )ñ )¨ñ )r&   c                 ó   € \        RR7      # )zLBoard-routing tools (kanban_list, kanban_unblock): hidden from task workers.FrY   r]   r"   r&   r$   Ú_check_kanban_orchestrator_modera   c   s   € ô  %Ô(Ð(r&   Úkanban_completeÚkanban_blockÚkanban_scheduleÚkanban_request_reviewÚkanban_request_changesc                  ó2   a € ] tR t^ttRtR V 3R lltRtV ;t# )Ú_RejectzECarries a finished ``tool_error`` payload out of a validation helper.c               ó   € V ^8„  d   QhRR/# )r   ÚmessagerC   r"   )r#   s   "r$   r%   Ú_Reject.__annotate__w   s   € ÷ .ñ . ñ .r&   c                	ó8   <€ \         SV `  \        V4      4       R # ©N)ÚsuperÚ__init__r   )Úselfrj   Ú	__class__s   &&€r$   ro   Ú_Reject.__init__w   s   ø€ Ü‰Ñœ GÓ,Ö-r&   r"   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ro   Ú__static_attributes__Ú__classcell__)rq   s   @r$   rh   rh   t   s   ø† ÙO÷.ö .r&   rh   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úcondr   rj   rC   r    ÚNoner"   )r#   s   "r$   r%   r%   {   s!   € ÷ ñ �ð ˜sð  tñ r&   c                ó,   € V '       g   \        V4      hR# )z3Reject (as a tool error) unless ``cond`` is truthy.N)rh   )r{   rj   s   &&r$   Ú_checkr~   {   s   € çÜ�gÓÐñ r&   Úkanban_createÚ
session_idÚ
project_idÚkanban_attach_urlÚtitlezdict[str, frozenset[str]]Ú_UNDECLARED_ARGSc               ó   € V ^8„  d   QhRR/# ©r   r    rC   r"   )r#   s   "r$   r%   r%   ‹   s   € ÷ 6ñ 6˜Sñ 6r&   c                 ó2   € ^ RI Hp  V ! R4      ;'       g    R# )u  Profile name persisted into board records (comment author, task creator).

``hermes_cli.profiles.current_profile_name`` resolves the profile this call runs FOR â€” the bound
home override under a multiplexed tick or turn, else the dispatcher's ``HERMES_PROFILE`` pin,
else the process home; the generic ``"worker"`` only when nothing names a profile. Never taken
from tool args: board records are injected into future workers' prompts, so a caller-supplied
identity could forge an authoritative-looking author (see #19713).
©Úcurrent_profile_nameÚworker)Úhermes_cli.profilesr‰   rˆ   s    r$   Ú_persisted_identityrŒ   ‹   s   € õ 9á Ó)×5Ð5¨XÐ5r&   c               ó    € V ^8„  d   QhRRRR/# )r   Ú	tool_namerC   r    r   r"   )r#   s   "r$   r%   r%   ™   s   € ÷ ñ ˜sð  xñ r&   c                ó   a € V 3R lpV# )zòWrap a handler so every failure is a structured tool error. ``ValueError``
(invalid board slug, DB validation such as cycle/self-link, ``AttachmentTooLarge``)
is reported without a traceback; anything else is logged with ``logger.exception``.c                óP   <a € \         P                  ! S 4      R  V V3R ll4       pV# )c               ó    € V ^8„  d   QhRRRR/# ©r   ÚargsÚdictr    rC   r"   )r#   s   "r$   r%   Ú3_kanban_handler.<locals>.deco.<locals>.__annotate__Ÿ   s   € ÷ 	7ñ 	7˜$ð 	7¨ñ 	7r&   c                ól  <€  \         P                  ! S4      R ,          R,          p\        V4      \        P	                  S\        4       4      ,          p\        \        V 4      V,
          4      p\        V'       * S RRP                  V4       RRP                  \        V4      4       R24       S! V 3/ VB #   \         d   pTP                  ^ ,          u Rp?# Rp?i\         dI   p\        T\        4      '       g   \        P                  S R24       \!        S RT 24      u Rp?# Rp?ii ; i)	Ú
parametersÚ
propertiesz: unknown parameter(s): ú, z. Valid parameters: z. Nothing changed.Nz failedú: )r
   Ú
get_schemaÚsetr„   r9   Ú	frozensetÚsortedr~   Újoinrh   r“   r=   r0   Ú
ValueErrorÚloggerÚ	exceptionr   )r“   Úkwr˜   ÚallowedÚunknownÚeÚfnrŽ   s   &,    €€r$   ÚwrapperÚ._kanban_handler.<locals>.deco.<locals>.wrapperž   s  ø€ ð7ä%×0Ò0°Ó;¸LÕIÈ,ÕW�
Ü˜j›/Ô,<×,@Ñ,@ÀÌIËKÓ,XÕX�Ü ¤ T£¨WÕ!4Ó5�Ü˜7”{Ø#˜Ð$<¸T¿Y¹YÀwÓ=OÐ<Pð Q,Ø,0¯I©I´f¸ZÓ6HÓ,IÐ+JÐJ\ð^ô_ñ ˜$‘~ "‘~Ð%øÜô !Ø—v‘v˜a•yÕ ûÜô 7Ü! !¤Z×0Ò0Ü×$Ñ$¨	 {°'Ð%:Ô;Ü! Y K¨r°!°Ð"5Ó6Õ6ûð7ús6   ƒB6B: Â:D3ÃCÃD3ÃD3Ã*D3Ã+=D.Ä(D3Ä.D3)Ú	functoolsÚwraps)r§   r¨   rŽ   s   f €r$   ÚdecoÚ_kanban_handler.<locals>.deco�   s*   ù€ Ü	�Š˜Ó	÷	7ð 	7ó 
ð	7ð  ˆr&   r"   )rŽ   r¬   s   f r$   Ú_kanban_handlerr®   ™   s   ø€ õð& €Kr&   c               ó    € V ^8„  d   QhRRRR/# ©r   rŽ   rC   r    r|   r"   )r#   s   "r$   r%   r%   ³   s   € ÷ Lñ L°ð L¸ñ Lr&   c                óF   € \        RR4      '       d   \        V  R24      hR# )zšA delegate_task child shares the parent's process, so inherited HERMES_KANBAN_*
env is not proof of ownership: it may report findings but must not mutate.Ú"is_delegated_child_process_contextFzÈ refused: delegate_task child agents are not Kanban run owners. Return findings to the parent agent; the dispatcher worker or an explicitly configured Kanban orchestrator must perform board mutations.N)rI   rh   ©rŽ   s   &r$   Ú _reject_delegated_child_mutationr´   ³   s8   € ô Ð;¸U×CÒCÜØˆkð Kð KóLð 	Lñ Dr&   c               ó    € V ^8„  d   QhRRRR/# )r   Úargr   r    úOptional[str]r"   )r#   s   "r$   r%   r%   ½   s   € ÷ ñ ˜#ð  -ñ r&   c                ó  € V e$   \        V 4      P                  4       pV'       d   V# \        4       '       d   R# \        4       '       g   R# \        P
                  P                  R4      pV'       d   VP                  4       pV'       d   V# R# )zGResolve ``task_id`` arg or fall back to the env var the dispatcher set.NrV   )rC   ÚstriprN   rR   rW   rX   r9   )r¶   ÚvalÚenv_tids   &  r$   Ú_default_task_idr¼   ½   se   € à
‚Ü�#‹h�n‰nÓˆßØˆJÜ"×$Ò$ÙÜ&×(Ò(ñ Ü�j‰j�n‰nÐ1Ó2€GßØ�m‰m‹oˆßØˆJÙr&   c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   Ñ   s   € ÷ Uñ U˜4ð U Cñ Ur&   c                óÀ   € \        V P                  R4      4      pV'       d   V# \        P                  P                  R4      '       d   \	        R4      h\	        R4      h)a  Resolve the target task or reject with a message the caller can act on.

The env default only exists for a dispatcher-spawned worker; every other
caller must name a task, so a rejection points at ``kanban_list`` instead of
an env var a chat caller cannot set (#91431).
Útask_idrV   zˆtask_id is required: this session does not own the inherited HERMES_KANBAN_TASK, so it is not a valid default. Pass an explicit task_id.zŽtask_id is required: this session has no dispatcher-assigned task to default to. Pass an explicit task_id; discover task ids with kanban_list.)r¼   r9   rW   rX   rh   )r“   Útids   & r$   Ú_require_task_idrÁ   Ñ   s^   € ô ˜4Ÿ8™8 IÓ.Ó
/€Cß
Øˆ
Ü	‡z�z‡~�~Ð*×+Ò+ô ðóð 	ô ð	TóUð Ur&   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r¿   rC   Úvarr    r·   r"   )r#   s   "r$   r%   r%   ç   s&   € ÷ \ñ \˜3ð \ Sð \¨]ñ \r&   c                óŒ   € \         P                  P                  R4      V 8X  d    \         P                  P                  V4      # R# )zC``$var`` only when this worker is scoped to ``task_id``; else None.rV   N)rW   rX   r9   )r¿   rÃ   s   &&r$   Ú_own_task_envrÅ   ç   s0   € ä"$§*¡*§.¡.Ð1EÓ"FÈ'Ô"QŒ2�:‰:�>‰>˜#ÓÐ[ÐW[Ð[r&   c               ó    € V ^8„  d   QhRRRR/# )r   r¿   rC   r    úOptional[int]r"   )r#   s   "r$   r%   r%   ë   s   € ÷ ñ ˜Cð  Mñ r&   c                ój   € \        V R4      p V'       d   \        V4      # R#   \         d     R# i ; i)z=This worker's dispatcher run id when it is scoped to task_id.ÚHERMES_KANBAN_RUN_IDN)rÅ   Úintr    )r¿   Úraws   & r$   Ú_worker_run_idrÌ   ë   s7   € ä
˜Ð!7Ó
8€CðßŒs�3‹xÐ( DÐ(øÜô Úðús   Ž# ¡# £2±2c               ó$   € V ^8„  d   QhRRRRRR/# )r   r¿   rC   ÚmetadataúOptional[dict]r    r"   )r#   s   "r$   r%   r%   ô   s&   € ÷ ]ñ ]¨Cð ]¸>ð ]Ènñ ]r&   c                óR   € \        V R4      pV'       d   / T;'       g    / CRV/C# T# )zBAdd trusted worker session id metadata for this worker's own task.ÚHERMES_SESSION_IDÚworker_session_id)rÅ   )r¿   rÎ   r€   s   && r$   Ú_stamp_worker_session_metadatarÓ   ô   s1   € ä˜wÐ(;Ó<€JßDNÐ@ˆx�~ˆ~˜2Ð@Ð 3°ZÑ@Ð\ÐT\Ð\r&   c               ó    € V ^8„  d   QhRRRR/# )r   rÀ   rC   r    r|   r"   )r#   s   "r$   r%   r%   ú   s   € ÷ bñ b¨ð b°ñ br&   c                óˆ   € \         P                  P                  R4      pV'       d   W8w  d   \        RV RV  R24      hR# R# )aÛ  A dispatcher-spawned worker may only mutate its own HERMES_KANBAN_TASK; a
prompt-injected ``task_id`` must not corrupt sibling/cross-tenant runs.
Orchestrators (toolset enabled, no env task) legitimately route child tasks.

Tools like ``kanban_complete`` / ``kanban_block`` / ``kanban_heartbeat`` mutate run-lifecycle state, so
a buggy or prompt-injected worker that passed an explicit ``task_id`` for some other task could corrupt
sibling or cross-tenant runs (see #19534).
rV   zworker is scoped to task z; refusing to mutate zf. Use kanban_comment to hand off information to other tasks, or kanban_create to spawn follow-up work.N©rW   rX   r9   rh   )rÀ   r»   s   & r$   Ú_enforce_worker_task_ownershipr×   ú   sO   € ô �j‰j�n‰nÐ1Ó2€Gß�3”>ÜØ'¨ yÐ0EÀcÀUð K`ð aóbð 	bñ "�wr&   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rŽ   rC   r“   r”   r    r"   )r#   s   "r$   r%   r%   
  s!   € ÷  ñ  ˜Sð  ¨ð  °ñ  r&   c                óÞ   € \        V 4       \        V4      p\        V4       V \        9   dA   \        P
                  P                  R4      '       d   \        V4      f   \        V  R24      hV# )a˜  Worker mutation preamble, in order: delegate-child rejection, task id
resolution, task-scope ownership, run-identity proof. Returns the task id.

A dispatcher-spawned worker (``HERMES_KANBAN_TASK`` set) that cannot name
its run id is refused on the run-lifecycle mutations: ``expected_run_id=None``
would silently skip the run-ownership CAS in ``kanban_db`` (``complete_task`` /
``block_task`` / ``request_review`` / ``request_changes`` only append
``AND current_run_id = ?`` when the value is not ``None``), so an unbound
stale worker could complete a card a live successor owns. This mirrors
``agent/kanban_stop.py``, which already treats an unbound run id as unknown
and fails closed. CLI / human / orchestrator paths (no ``HERMES_KANBAN_TASK``)
legitimately pass ``expected_run_id=None`` and are unaffected. Non-lifecycle
worker tools (heartbeat / attach / attach_url) do not terminate a run and are
not gated here.
rV   a@   refused: this worker cannot resolve its HERMES_KANBAN_RUN_ID, so it cannot prove ownership of the card's current run. A stale or unbound worker must not terminate a run a live successor owns. Re-run through the dispatcher so the run id is pinned, or use an orchestrator/CLI path that passes an explicit expected_run_id.)	r´   rÁ   r×   Ú_RUN_LIFECYCLE_TOOLSrW   rX   r9   rÌ   rh   )rŽ   r“   rÀ   s   && r$   Ú_worker_guardrÛ   
  si   € ô  % YÔ/Ü
˜4Ó
 €CÜ" 3Ô'àÔ)Ô)Ü�J‰J�N‰NÐ/×0Ò0Ü˜3ÓÒ'äØˆkð ð ó
ð 	
ð €Jr&   c               ó    € V ^8„  d   QhRRRR/# r°   r"   )r#   s   "r$   r%   r%   -  s   € ÷ Lñ L¨#ð L°$ñ Lr&   c                ól   € \         P                  P                  R4      '       d   \        V  R24      hR# )z‹The check_fn already hides orchestrator tools from workers; this catches
a stale registration or test harness routing a worker here anyway.rV   zÅ is orchestrator-only; dispatcher-spawned workers must use kanban_complete, kanban_request_review, kanban_request_changes, kanban_block, kanban_heartbeat, or kanban_comment for their assigned task.NrÖ   r³   s   &r$   Ú_require_orchestrator_toolrÞ   -  s=   € ô 
‡z�z‡~�~Ð*×+Ò+ÜØˆkð Kð KóLð 	Lñ ,r&   Úquiet_closeFc               ó    € V ^8„  d   QhRRRR/# )r   Úboardr·   rß   r!   r"   )r#   s   "r$   r%   r%   8  s   € ÷ ñ �-ð °ñ r&   c             #  ó  "  € ^ RI Hp ^ RI Hp VP                  V R7      p W$3x €  VP	                  4        R#   \
         d    T'       g   h  R# i ; i   TP	                  4        i   \
         d    T'       g   h  i i ; i; i5i)zú``with _board(slug) as (kb, conn)``; lazy import so the module loads in non-kanban
contexts. ``board=None`` keeps the env/symlink resolution chain; an explicit slug
overrides it per call. ``quiet_close`` swallows close() errors (best-effort bridges).©Ú	kanban_db)Úkanban_db_connect)rá   N)Ú
hermes_clirä   rå   ÚconnectÚcloser=   )rá   rß   ÚkbÚkbcÚconns   &$   r$   Ú_boardrì   7  sx   é € õ
 +Ý3Ø�;‰;˜Uˆ;Ó#€DðØˆhŠð	Ø�J‰JŽLøÜô 	ßØò ð	ûð	Ø�J‰J�LøÜô 	ßØñ ð	ÿsf   ‚B¢A ¨: ¸BºAÁAÁBÁAÁBÁBÁA(Á'BÁ(A?Á;A?Á<BÁ>A?Á?BÂBc               ó   € V ^8„  d   QhRR/# )r   rÀ   rC   r"   )r#   s   "r$   r%   r%   I  s   € ÷ ñ  #ñ r&   c                óL   € V P                  W4      p\        VR JRV R24       V# )Nztask z
 not found)Úget_taskr~   )ré   rë   rÀ   Útasks   &&& r$   Ú_existing_taskrñ   I  s-   € Ø�;‰;�tÓ!€DÜ
ˆ4�tÐ˜u S E¨Ð4Ô5Ø€Kr&   c               ó    € V ^8„  d   QhRRRR/# )r   Úfieldsr   r    rC   r"   )r#   s   "r$   r%   r%   O  s   € ÷ .ñ .�#ð .˜#ñ .r&   c                 ó6   € \         P                  ! R R/V C4      # )ÚokT)ÚjsonÚdumps)ró   s   ,r$   Ú_okrø   O  s   € Ü�:Š:�t˜TÐ, VÐ,Ó-Ð-r&   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   rÀ   rC   Údefault_statusÚextrar   r    r"   )r#   s   "r$   r%   r%   S  s.   € ÷ Lñ L˜cð L°3ð LÀð LÈñ Lr&   c           	     ó¸   € V P                  W4      pV P                  W4      p\        RRTRV'       d   VP                  MRRV'       d   VP                  MT/VB # )zlSuccess payload reporting where the task actually landed (routing may
not leave it in the requested status).r¿   Úrun_idNÚstatusr"   )Ú
latest_runrï   rø   Úidrþ   )ré   rë   rÀ   rú   rû   ÚrunÚlandeds   &&&&,  r$   Ú
_ok_landedr  S  sa   € ð �-‰-˜Ó
"€CØ�[‰[˜Ó#€FÜñ L�sð L¯S 3§6¢6°dð Lß'-�f—m’m°>ðLØEJñLð Lr&   c               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   r    rC   r"   )r#   s   "r$   r%   r%   \  s   € ÷ 9ñ 9�3ð 9˜3ñ 9r&   c                ó.   € \        \        V 4      R R7      # )T©Úforce)r   rC   ©r  s   &r$   Ú_redactr
  \  s   € Ü ¤ U£°4Ô8Ð8r&   c               ó    € V ^8„  d   QhRRRR/# )r   r  r   r    r"   )r#   s   "r$   r%   r%   `  s   € ÷ .ñ .�sð .˜sñ .r&   c                ó,   € V '       d   \        V 4      # T # rm   )r
  r	  s   &r$   Ú_redact_optr  `  s   € ß"Œ7�5‹>Ð-¨Ð-r&   c               ó    € V ^8„  d   QhRRRR/# )r   rÎ   r”   r    rÏ   r"   )r#   s   "r$   r%   r%   d  s   € ÷ ñ ˜tð ¨ñ r&   c                ó¦   €  \         P                  ! \        \         P                  ! V 4      RR7      4      #   \         P                   d     R# i ; i)zDRedact via a JSON round-trip; None if the result can't be re-parsed.Tr  N)rö   Úloadsr   r÷   ÚJSONDecodeError©rÎ   s   &r$   Ú_redact_metadatar  d  s?   € ðÜ�zŠzÔ/´·
²
¸8Ó0DÈDÔQÓRÐRøÜ×Ñô Úðús   ‚47 ·AÁAr¹   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r  r   ÚnamerC   Úwhatr¹   r!   r"   )r#   s   "r$   r%   r%   l  s(   € ÷ ñ ˜Cð  sð °#ð Àñ r&   c          	     ót  € V f   R# \        V \        4      '       d   V .p \        V \        \        34      '       g'   \	        V RV R\        V 4      P                   24      hV'       dJ   V  Uu. uF=  p\        V4      P                  4       '       g   K$  \        V4      P                  4       NK?  	  p pV # u upi )z~Accept a single string (convenience) or a list/tuple; with ``strip`` the
items are stringified, stripped, and empties dropped.Nz must be a list of z, got )r0   rC   r1   Útuplerh   Útypers   r¹   )r  r  r  r¹   Úxs   &&&$ r$   Ú_coerce_str_listr  l  s“   € ð ‚}ÙÜ�%œ×ÒØ�ˆÜ�eœd¤E˜]×+Ò+Ü˜˜Ð1°$°°v¼dÀ5»k×>RÑ>RÐ=SÐTÓUÐUßÙ).ÓA© A´#°a³&·,±,·.””�Q“—‘–©ˆÐAØ€Lùò Bs   Á.!B5ÂB5c               ó    € V ^8„  d   QhRRRR/# )r   rÎ   r   r    r|   r"   )r#   s   "r$   r%   r%   z  s   € ÷ Nñ N Sð N¨Tñ Nr&   c                ó~   € \        V R J ;'       g    \        V \        4      R\        V 4      P                   24       R # )Nz%metadata must be an object/dict, got )r~   r0   r”   r  rs   r  s   &r$   Ú_require_dict_metadatar  z  s6   € Ü
ˆ8�tÐ×9Ð9œz¨(´DÓ9Ø2´4¸³>×3JÑ3JÐ2KÐLöNr&   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rÎ   r   Ú	artifactsz	list[str]r    r”   r"   )r#   s   "r$   r%   r%     s!   € ÷ ñ ˜sð ¨yð ¸Tñ r&   c                óü   € \        V 4       V f   / MT p V P                  R4      p\        V\        \        34      '       d8   R . VOVO 4       p\        \
        P                  R V 4       4      4      V R&   V # WR&   V # )a  Fold ``artifacts`` into ``metadata["artifacts"]`` (merged with, never overwriting, a
list the worker passed manually). Artifacts ride inside metadata so the completed-event
payload needs no DB schema change; the gateway notifier uploads each as an attachment.r   c              3  óT   "  € T F  p\        V4      P                  4       x € K   	  R # 5irm   )rC   r¹   )r2   Úitems   & r$   r6   Ú#_merge_artifacts.<locals>.<genexpr>‡  s    é € ÐHÑ0G¨”#�d“)—/‘/×#Ð#Ó0Gùs   ‚&(c              3  ó8   "  € T F  q'       g   K  Vx € K  	  R # 5irm   r"   )r2   Úss   & r$   r6   r$  ˆ  s   é € Ð2J¹f¸Ë·1²1»fùs   ‚	�
)r  r9   r0   r1   r  r”   Úfromkeys)rÎ   r   ÚexistingÚmergeds   &&  r$   Ú_merge_artifactsr*    s€   € ô ˜8Ô$ØÒ%‰r¨8€HØ�|‰|˜KÓ(€HÜ�(œT¤5˜M×*Ò*ÙHÐ0G°(Ð0G¸YÑ0GÓHˆÜ $¤T§]¡]Ñ2J¹fÓ2JÓ%JÓ Kˆ�Ñð €Oð !*�ÑØ€Or&   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r“   r”   r  rC   rj   r·   r    r   r"   )r#   s   "r$   r%   r%   Ž  s(   € ÷ ñ ˜ð  Cð °-ð È3ñ r&   c                óœ   € V P                  V4      p\        T;'       d    \        V4      P                  4       T;'       g    V R24       V# )z.``args[name]``; rejects when missing or blank.z is required)r9   r~   rC   r¹   )r“   r  rj   r  s   &&& r$   Ú_require_textr-  Ž  sB   € à�H‰H�T‹N€EÜ
ˆ5×'Ð'”S˜“Z×%Ñ%Ó'¨×)IÐ)I°t°f¸LÐ4IÔJØ€Lr&   ÚtrueTÚ1ÚyesÚfalseÚ0Únoc               ó$   € V ^8„  d   QhRRRRRR/# )r   r“   r”   r  rC   r    r!   r"   )r#   s   "r$   r%   r%   ˜  s!   € ÷ ñ ˜$ð  cð ¨dñ r&   c                ó  € V P                  V4      pVe   \        V\        4      '       d   \        V4      # \        P                  \	        V4      P                  4       P                  4       4      p\        VR JV R24       V# )Nz$ must be a boolean or 'true'/'false')r9   r0   r!   Ú_BOOL_WORDSrC   r¹   Úlowerr~   )r“   r  r  Úparseds   &&  r$   Ú_parse_bool_argr9  ˜  sj   € Ø�H‰H�T‹N€EØ‚}œ
 5¬$×/Ò/Ü�E‹{ÐÜ�_‰_œS ›Z×-Ñ-Ó/×5Ñ5Ó7Ó8€FÜ
ˆ6˜Ð $ Ð'KÐLÔMØ€Mr&   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r   rD   rÇ   r    r"   )r#   s   "r$   r%   r%   ¡  s!   € ÷ 8ñ 8�Cð 8 -ð 8¸=ñ 8r&   c                ó$   € V e   \        V 4      # T# rm   )rÊ   )r  rD   s   &&r$   Ú_opt_intr<  ¡  s   € ØÒ*Œ3ˆu‹:Ð7°Ð7r&   z×id title body assignee status tenant priority workspace_kind workspace_path created_by created_at started_at completed_at result current_run_id model_override provider_override completion_contract last_failure_errorz¯id title assignee status priority tenant workspace_kind workspace_path project_id created_by created_at started_at completed_at current_run_id model_override provider_overridezDid profile status outcome summary error metadata started_at ended_atz@id filename content_type size uploaded_by stored_path created_atc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úobjr   r4   ztuple[str, ...]r    údict[str, Any]r"   )r#   s   "r$   r%   r%   ´  s&   € ÷ Lñ L�ð L˜_ð L°ñ Lr&   c                óN   € V Uu/ uF  q"V e   \        W4      MRbK  	  up# u upi )zF``{name: getattr(obj, name)}``; every value None when ``obj`` is None.N)rH   )r>  r4   Úns   && r$   Ú_fieldsrB  ´  s'   € áEJÓKÁUÀ #¢/Œw�sŒ°tÒ;ÁUÑKÐKùÒKs   …"c               ó   € V ^8„  d   QhRR/# )r   r    r?  r"   )r#   s   "r$   r%   r%   ¹  s   € ÷ Dñ D¨.ñ Dr&   c                óÊ   € V P                  WP                  4      pV P                  WP                  4      p/ \        V\        4      CR VRVR\        V4      R\        V4      /C# )ÚparentsÚchildrenÚparent_countÚchild_count)Ú
parent_idsr   Ú	child_idsrB  Ú_TASK_SUMMARY_FIELDSÚlen)ré   rë   rð   rE  rF  s   &&&  r$   Ú_task_summary_dictrM  ¹  sc   € Ø�m‰m˜D§'¡'Ó*€GØ�|‰|˜D§'¡'Ó*€HðDÜ
�$Ô,Ó
-ðDØ/8¸'À:ÈxØœ˜G› m´S¸³]ñDð Dr&   Ú
dependencyÚneeds_inputc               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   Æ  s   € ÷ 	.ñ 	.˜tñ 	.r&   c                 óv   €  ^ RI Hp  V ! R4      w  rTRJ;'       d    \        T4      #   \         d     R# i ; i)zÙ``judge_goal`` fails open (no auxiliary model -> ``"continue"``), which is
indistinguishable from "not done yet" and would wedge every goal_mode
worker; so the gate is enforced only when a judge is actually reachable.)Úget_text_auxiliary_clientÚ
goal_judgeFN)Úagent.auxiliary_clientrR  r=   r!   )rR  ÚclientÚmodels      r$   Ú_goal_judge_availablerW  Æ  sC   € ðÝDÙ1°,Ó?‰ˆð ˜Ð×-Ð-¤$ u£+Ð-øô ô Úðús   ‚) ©8·8Úblockeduì   Goal completion rejected: judge ruled the goal unachievable â€” {reason}. The task will NOT complete silently. Either re-scope the task with kanban_edit, or record the block with kanban_block and hand the decision to a human / reviewer.ÚcontinuezçGoal completion rejected by judge: {reason}. To proceed, either: (1) provide explicit acceptance evidence in your summary matching the task's criteria, or (2) create continuation tasks with parents=[{tid}] and keep this task alive.uŽ   Goal review handoff rejected: judge ruled the goal unachievable â€” {reason}. Record the block with kanban_block instead of requesting review.zxGoal review handoff rejected by judge: {reason}. Provide acceptance evidence matching the card before requesting review.c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   rŽ   rC   rÀ   Úevidencer    r|   r"   )r#   s   "r$   r%   r%   æ  s.   € ÷ Vñ V˜#ð V¨#ð V¸ð VÀñ Vr&   c                ó¦  € V'       d#   VP                   '       d   \        4       '       g   R#  ^ RIHpHpHp V! 4       '       d   RM
V! RV 24      p \        VP                   RVP                  ;'       g    R 2P                  4       VP                  4       R7      w  r‰ r«Ve	   V! V4       T'       d   \        P                  R
T	4       R# TR8X  d   R# TR8X  d   RMRp\        \        T ,          T,          P                  Y’R7      4      h  Te
   T! T4       i i ; i  \         d$   p\        P                  RTRR	7        Rp?R# Rp?ii ; i)a  Goal-mode pre-handoff judge gate: a worker must not complete / request
review before acceptance criteria are met. ``blocked`` gets its own
guidance; any other non-``done`` verdict gets the ``continue`` guidance.
A broken judge fails open (logged) so it cannot permanently wedge work.N)Úget_affinity_scopeÚreset_affinity_scopeÚset_affinity_scopezkanban:z

Ú )ÚgoalÚlast_responsez7goal judge check failed, allowing lifecycle handoff: %sT©Úexc_infoz7goal judge unreachable (%s), allowing lifecycle handoffÚdonerX  rY  )ÚreasonrÀ   )Ú	goal_moderW  Úagent.portal_tagsr]  r^  r_  r   rƒ   Úbodyr¹   r=   r¡   Úwarningrh   Ú_GOAL_GATE_MESSAGESr#   )rŽ   rð   rÀ   r[  r]  r^  r_  Úaffinity_tokenÚverdictrf  Ú_Útransport_failedÚ	judge_excÚkeys   &&&&          r$   Ú
_goal_gaterr  æ  s:  € ÷
 �t—~—~�~Ô-B×-DÒ-DÙð÷ 	cÑbÙ!3×!5Ò!5™Ñ;MÐPWÐX[ÐW\ÈoÓ;^ˆð	5Ü6@ØŸ
™
�| 4¨¯	©	¯¨°RÐ'8Ð9×?Ñ?ÓAÐQY×Q_ÑQ_ÓQaô7cÑ3ˆG˜Q ð Ò)Ù$ ^Ô4÷
 ô 	�‰ÐPÐRXÔYÙØ�&ÔÙØ )Ô+‰)°€CÜ
Ô% iÕ0°Õ5×<Ñ<ÀFÐ<ÓTÓ
UÐUøð Ò)Ù$ ^Õ4ð *ûäô Ü�‰ØEÀyÐ[_ð 	ô 	aåûðús;   ®D" ÁD" Á$D Á8+D Â#D" ÄDÄD" Ä"EÄ-EÅEg      N@g        ÚfloatÚ_auto_heartbeat_last_attemptc               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%      s   € ÷ ñ ¨$ñ r&   c            	     ó°  € \         P                  P                  R4      p V '       d   \        V 4      MRpVe   \	        4       '       d   R#  ^ RIHp \        RRR7      ;_uu_ 4       w  r4VP                  W@V\         P                  ! 4       4      uuRRR4       #   + '       g   i     R# ; i  \         d    \        P                  RT RR7        R# i ; i)a  Record this worker's pid on its run when the dispatcher died before it could
(``adopt_worker_pid``). False only when the board says the run was already reclaimed:
the caller must exit. Anything unreadable (no run id, delegate child, board error)
lets the worker run, as before.rV   NT©Úkanban_db_dispatch©rß   z(kanban worker registration for %s failedrc  )rW   rX   r9   rÌ   rN   ræ   rx  rì   Úadopt_worker_pidÚgetpidr=   r¡   Údebug)rÀ   rý   ÚkbdÚ_kbrë   s        r$   Ú register_current_worker_from_envr     sš   € ô
 �*‰*�.‰.Ð-Ó
.€Cß$'Œ^˜CÔ ¨T€FØ‚~Ô4×6Ò6ÙðÝ8Ü�D d×+Õ+©{°Ø×'Ñ'¨°6¼2¿9º9»;ÓG÷ ,×+×+Ó+ûäô Ü�‰Ð?ÀÈtˆÔTÚðús0   ÁB. Á'(BÂ
B. ÂB+	Â%B. Â+B. Â.#CÃCc               ó   € V ^8„  d   QhRR/# r   r"   )r#   s   "r$   r%   r%   2  s   € ÷ ,ñ ,¨4ñ ,r&   c            
     ór  € \         P                  P                  R4      p \        P                  ! 4       pV '       d   V\
        ,
          \        8  d   R# \        4       '       d   R# Ts ^ RIH	p \        RRR7      ;_uu_ 4       w  r4VP                  R\         P                  P                  R4      /3VP                  R	RR
\        V 4      /33pRpV F.  w  rxVP                  p	 \        V! W@3/ VB 4      ;'       d    TpK0  	  RRR4       V#   \          d8   p
Rp\"        '       g   Rs\$        P'                  RY
4        Rp
?
Ks   Rp
?
Ky  Rp
?
i\(         d    \$        P+                  RT	RR7       Rp K¤  i ; i  + '       g   i     X# ; i  \(         d    \$        P+                  RRR7        R# i ; i)zöClaim extension + board heartbeat for the current worker; True iff both writes
succeed. ``HERMES_KANBAN_RUN_ID`` pins the run row so a reclaimed stale run is not
heartbeated; ``HERMES_KANBAN_CLAIM_LOCK`` absent -> default claimer (local workers).rV   Frw  NTry  ÚclaimerÚHERMES_KANBAN_CLAIM_LOCKÚnoteÚexpected_run_ida`  kanban auto-heartbeat for task %s refused (%s): this process carries HERMES_DELEGATED_CHILD_CONTEXT together with HERMES_KANBAN_TASK, so the board treats it as a delegate_task descendant and its claim will not be extended by activity. Only the dispatcher's own spawn grants worker scope; do not copy a worker's environment into a hand-launched process.zauto-heartbeat: %s failedrc  zauto-heartbeat: bridge failed)rW   rX   r9   ÚtimeÚ	monotonicrt  Ú$_AUTO_HEARTBEAT_MIN_INTERVAL_SECONDSrN   ræ   rx  rì   Úheartbeat_claimÚheartbeat_workerrÌ   rs   r!   ÚPermissionErrorÚ_auto_heartbeat_fence_warnedr¡   rj  r=   r|  )rÀ   Únowr}  ré   rë   ÚopsÚ	succeededr§   ÚkwargsÚopÚexcs              r$   Ú!heartbeat_current_worker_from_envr“  2  s“  € ô
 �*‰*�.‰.Ð-Ó
.€CÜ
�.Š.Ó
€Cß�3Ô5Õ5Ô9]Ô]ÙÜ"×$Ò$ñ Ø#&Ð ðÝ8Ü�D d×+Õ+©z°Ø×&Ñ&¨´B·J±J·N±NÐC]Ó4^Ð(_Ð`Ø×(Ñ(¨6°4Ð9JÌNÐ[^ÓL_Ð*`ÐaðcˆCàˆIÛ!‘
�Ø—[‘[�ð&Ü $¡R¨Ñ%<°VÑ%<Ó =× KÐ KÀ)’Iñ "÷	 ,ð2 Ðøô# 'ô \ð
 !&�Iß7Ó7Ø7;Ð4ÜŸ™ðQð SV÷\ò \õ 8ûô !ô &Ü—L‘LÐ!<¸bÈ4�LÔPØ %“Ið&ú÷- ,Ö+ð2 ÐûÜô Ü�‰Ð4¸tˆÔDÚðúsm   Á*F ÂA E<Ã&DÄE<Ä	F ÄE9	Ä&E	ÅE<ÅE9	ÅE9	Å5E<Å8E9	Å9E<Å<F	ÆF ÆF Æ"F6Æ5F6g      @Ú_comment_poll_last_attemptzdict[str, int]Ú_comment_watermarkc               ó    € V ^8„  d   QhRRRR/# )r   rG   r   r    r!   r"   )r#   s   "r$   r%   r%   i  s   € ÷ (ñ (¨ð (°ñ (r&   c                ó@  € \        4       '       d    \        P                  P                  R4      MRp\        P
                  ! 4       pV'       d-   V e)   \        V R4      '       d   V\        ,
          \        8  d   R# Vs\        P                  V4      p \        RRR7      ;_uu_ 4       w  rETP                  YQT;'       g    ^ R7      pRRR4       Tf   \        R
 X 4       ^ R7      \        T&   Te	   X'       g   R# \        R T 4       4      \        T&   \!        4       pT Uu. uF[  qˆP"                  ;'       g    RP%                  4       T8w  g   K-  TP&                  ;'       g    RP%                  4       '       g   KY  TNK]  	  p	pT	'       g   R# T	 Uu. uF7  pRTP"                  ;'       g    R RTP&                  P%                  4        2NK9  	  p
pR\)        T	4      ^8”  d   RMR,           R,           R,           RP+                  T
4      ,           p \-        T P/                  T4      4      #   + '       g   i     ELo; i  \         d    \        P                  RRR	7        R# i ; iu upi u upi   \         d    \        P                  RRR	7        R# i ; i)z¡Steer new operator comments on the worker's task into ``agent``; True iff a
steer was injected; never raises. Own comments (``_persisted_identity``) are skipped.rV   NÚsteerFTry  )Úafter_idzcomment-inject: bridge failedrc  c              3  ó8   "  € T F  qP                   x € K  	  R # 5irm   ©r   ©r2   Úcs   & r$   r6   Ú/inject_new_comments_from_env.<locals>.<genexpr>}  s   é € Ð&:±T°§t¦t³Tùó   ‚©rD   c              3  ó8   "  € T F  qP                   x € K  	  R # 5irm   r›  rœ  s   & r$   r6   rž  �  s   é € Ð!5±¨1§$¦$³ùrŸ  r`  z- Úoperatorrš   zNew noter&  z< on your kanban task from the operator (delivered mid-run). z:Take it into account for the work you're doing right now:
Ú
zcomment-inject: steer failed)rR   rW   rX   r9   r†  r‡  Úhasattrr”  Ú"_COMMENT_POLL_MIN_INTERVAL_SECONDSr•  rì   Úlist_comments_afterr=   r¡   r|  ÚmaxrŒ   Úauthorr¹   ri  rL  rŸ   r!   r˜  )rG   rÀ   r�  Úseenré   rë   ÚrowsÚownr�  ÚfreshÚlinesr„  s   &           r$   Úinject_new_comments_from_envr®  i  s  € ô 3N×2OÒ2OŒ"�*‰*�.‰.Ð-Ô
.ÐUY€CÜ
�.Š.Ó
€Cß�5’=¬°°w×(?Ò(?ØÔ0Õ0Ô4VÔVÙØ!$ÐÜ×!Ñ! #Ó&€DðÜ�D d×+Õ+©z°Ø×)Ñ)¨$¸d¿i¸iÀaÐ)ÓHˆD÷ ,ð
 ‚|Ü"%Ñ&:±TÓ&:ÀAÔ"FÔ˜3ÑØ‚|Ÿ4Ùä!Ñ!5±Ó!5Ó5Ô�sÑô Ó
€CÙÓ[™�1§¡§ ¨R× 6Ñ 6Ó 8¸CÑ ?ŒQÀQÇVÁVÇ\À\Èr×DXÑDX×DZ�QˆQ™€EÐ[ßÙÙFKÓLÁeÀˆr�!—(‘(×(Ð(˜jÐ)¨¨A¯F©F¯L©L«NÐ+;Ó<Áe€EÐLØ¤ U£¨a¤™#°RÕ8ØLõMàKõLàNRÏiÉiÐX]ÓN^õ_€DðÜ�E—K‘K Ó%Ó&Ð&÷/ ,×+Ð+ûäô Ü�‰Ð4¸tˆÔDÚðüò \ùò Møô ô Ü�‰Ð3¸dˆÔCÚðúsl   ÂI Â* H0Ã
I Ä&I-Ä=I-ÅI-Å(I-ÆI-ÆI2Æ0$I2ÈI7 È0I	È;I ÉI É"I*É)I*É7"JÊJÚkanban_showc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   —  s   € ÷ Cñ C�tð C cñ Cr&   c                óf  € \        V P                  R4      4      pV'       g   \        P                  ! RRRR/4      # \	        V P                  R4      4      ;_uu_ 4       w  r4\        W4V4      p\        P                  ! R\        V\        4      RVP                  WB4      R	VP                  WB4       UUu. uF  w  rgR
VRV/NK  	  uppRVP                  WB4      RVP                  WB4       Uu. uF  p\        V\        4      NK  	  upRVP                  WB4      RR  U	u. uF  p	\        V	\        4      NK  	  up	RVP                  WB4       U
u. uF  p
\        V
\         4      NK  	  up
RVP#                  WB4      /4      uuRRR4       # u uppi u upi u up	i u up
i   + '       g   i     R# ; i)zHFull task state: row, parents, children, comments, runs, last 50 events.r¿   Úcurrent_taskNÚhintz²No dispatcher-assigned task in this session, so there is no task to show by default. Call kanban_list to see task ids on the board, then kanban_show(task_id=<id>) for full state.rá   rð   rE  Úunsatisfied_parentsr   rþ   rF  ÚcommentsÚeventsÚrunsÚworker_contextiÎÿÿÿ)r¼   r9   rö   r÷   rì   rñ   rB  Ú_TASK_FIELDSrI  r´  rJ  Úlist_commentsÚ_COMMENT_FIELDSÚlist_eventsÚ_EVENT_FIELDSÚ	list_runsÚ_RUN_FIELDSÚbuild_worker_context)r“   r£   rÀ   ré   rë   rð   Úpidrþ   r�  r¦   Úrs   &,         r$   Ú_handle_showrÃ  –  sŠ  € ô ˜4Ÿ8™8 IÓ.Ó
/€Cßô �zŠzØ˜DØðLð
ó ð 	ô 
�—‘˜Ó!×	"Ô	"¡j rÜ˜b¨Ó,ˆÜ�zŠzØ”G˜D¤,Ó/Ø�r—}‘} TÓ/ð "ØAC×AWÑAWÐX\ÔAbô$dÙAb±+°#��s˜H fÓ-ÑAbò$dà˜Ÿ™ TÓ/Ø¸b×>NÑ>NÈtÔ>YÓZÑ>Y¸œ ¤OÖ4Ñ>YÑZà¸"¿.¹.ÈÓ:SÐTWÐTXÑ:YÓZÑ:Y°Q”w˜q¤-Ö0Ñ:YÑZØ°b·l±lÀ4Ô6MÓNÑ6M°”W˜Q¤Ö,Ñ6MÑNà˜b×5Ñ5°dÓ@ðBó C÷ 
#Ò	"ùó$dùò [ùâZùÚN÷ 
#×	"Ð	"úsC   ÁAFÂ4F
Ã(FÃ-FÄFÄF"Ä8FÅF&Å'FÆ
FÆF0	Úkanban_listc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   ¸  s   € ÷ #ñ #�tð # cñ #r&   c                ó\  € \        R4       \        V R4      pV P                  R4      p Vf   \        M
\	        V4      p\        T^8¬  R4       \        T\        8*  R\         24       \        T P                  R4      4      ;_uu_ 4       w  rETP                  T4      pTP                  YPP                  R	4      T P                  R
4      T P                  R4      Y#^,           R7      p\        T4      T8„  pTRT p	\        P                  ! RT	 U
u. uF  p
\!        YET
4      NK  	  up
R\        T	4      RTRTRT'       d#   T\        8  d   \#        T^,          \        4      MRRT/4      uuRRR4       #   \
        \        3 d    \        R4      u # i ; iu up
i   + '       g   i     R# ; i)z5Task summaries with the same core filters as the CLI.rÄ  Úinclude_archivedÚlimitNzlimit must be an integerzlimit must be >= 1zlimit must be <= rá   Úassigneerþ   Útenant)rÉ  rþ   rÊ  rÇ  rÈ  ÚtasksÚcountÚ	truncatedÚ
next_limitÚpromoted)rÞ   r9  r9   ÚKANBAN_LIST_DEFAULT_LIMITrÊ   Ú	TypeErrorr    r   r~   ÚKANBAN_LIST_MAX_LIMITrì   Úrecompute_readyÚ
list_tasksrL  rö   r÷   rM  Úmin)r“   r£   rÇ  rÈ  ré   rë   rÏ  rª  rÍ  rË  Úts   &,         r$   Ú_handle_listr×  ·  s�  € ô ˜}Ô-Ü& tÐ-?Ó@ÐØ�H‰H�WÓ€Eð6Ø-2ª]Õ)ÄÀEÃ
ˆô ˆ5�A‰:Ð+Ô,Ü
ˆ5Ô)Ñ)Ð->Ô?TÐ>UÐ+VÔWÜ	�—‘˜Ó!×	"Ô	"¡j rð ×%Ñ% dÓ+ˆà�}‰}ØŸ8™8 JÓ/¸¿¹ÀÓ8JØ—8‘8˜HÓ%Ð8HÐXYÕPYð ó [ˆô ˜“I Ñ%ˆ	Ø�V�e�ˆÜ�zŠzØ¹uÓE¹u¸!Ô(¨°1Ö5¹uÑEØ”S˜“Z ¨%°¸iØß'¨EÔ4IÔ,Iô ˜u q�yÔ*?Ô@ØOSØ˜ð"ó #÷ 
#Ò	"øô	 ”zÐ"ô 6ÜÐ4Ó5Ò5ð6üò F÷ 
#×	"Ð	"ús1   ªE3 Â
BFÄFÄ$AFÅ3FÆFÆFÆF+	c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   Ö  s"   € ÷ RAñ RA˜4ð RA¨#ñ RAr&   c                óæ  € \        RV 4      p\        V P                  R4      4      p\        V P                  R4      4      pV P                  R4      p\        V\        4      '       d   \        V4      ;'       g    Tp\        V P                  R4      RRRR7      p\        V P                  R	4      R	R
RR7      pV'       d   \        WW4      p\        T;'       g    TR4       \        V4       \        W%4      p\        V P                  R4      4      ;_uu_ 4       w  r‰VP                  W’4      p
\        RY¢T;'       g    T;'       g    RP                  4       4        VP                  W’WCVV\!        V4      R7      pTP                  Y’4      p
T'       gr   TP1                  Y’4      pT'       d+   RP+                  R T 4       4      p\3        RT RT R24      h\        RT
'       d   T
P4                  MR;'       g    RT R24       TP7                  Y’4      p\9        TT'       d   TP:                  MRTP=                  Y’4       Uu. uF  p\?        T\@        4      NK  	  upR 7      uuRRR4       #   TP"                   d$   p\%        RT R24      u Rp?uuRRR4       # Rp?iTP&                   d'   p\%        RT RT R24      u Rp?uuRRR4       # Rp?iTP(                   d=   p\%        RRP+                  TP,                  4       R24      u Rp?uuRRR4       # Rp?iTP.                   d$   p\%        RT R24      u Rp?uuRRR4       # Rp?ii ; iu upi   + '       g   i     R# ; i)!z5Mark the current task done with a structured handoff.rb   ÚsummaryÚresultrÎ   Úcreated_cardsútask idsT©r¹   r   ú
file pathsz4provide at least one of: summary (preferred), resultrá   r`  )rÛ  rÚ  rÎ   rÜ  r…  z;kanban_complete could not preserve the declared artifacts: zœ. Your task is still in-flight and its scratch workspace was kept. Fix the artifact path or storage error, then retry kanban_complete with the same handoff.Nzkanban_complete refused: zi. Nothing changed. Wait for the worker to finish, or an operator can run `hermes kanban complete --force z`.zfkanban_complete blocked: the following created_cards do not exist or were not created by this worker: r™   zÔ. Your task is still in-flight (no state change). Retry kanban_complete with the same summary/metadata and either drop these ids from created_cards, or pass created_cards=[] to skip the card-claim check entirely.zkanban_complete blocked: z„. Your task is still in-flight (no state change). Retry kanban_complete with a non-empty summary or result describing what was done.c              3  ó6   "  € T F  w  rV R V R2x € K  	  R# 5i)z (Ú)Nr"   )r2   rÁ  rþ   s   &  r$   r6   Ú#_handle_complete.<locals>.<genexpr>  s   é € Ð"SÉ(¹;¸3 c U¨"¨V¨H°AÕ#6Ë(ùs   ‚zcould not complete z#: unsatisfied parent dependencies: z/; complete the parents first (done or archived)Fz- (unknown id, stale run, or already terminal))r¿   rý   Úattachments)!rÛ   r  r9   r0   r”   r  r  r*  r~   r  rÓ   rì   rï   rr  r¹   Úcomplete_taskrÌ   ÚArtifactPreservationErrorr   ÚLiveClaimErrorÚHallucinatedCardsErrorrŸ   ÚphantomÚEmptyCompletionErrorr´  rh   Úlast_failure_errorrÿ   rø   r   Úlist_attachmentsrB  Ú_ATTACHMENT_FIELDS)r“   r£   rÀ   rÚ  rÛ  rÎ   rÜ  r   ré   rë   rð   rõ   Úartifact_errÚ	claim_errÚhall_errÚ	empty_errÚblockersÚdetailr  Úas   &,                  r$   Ú_handle_completerô  Õ  se  € ô Ð)¨4Ó
0€CÜ˜$Ÿ(™( 9Ó-Ó.€GÜ˜Ÿ™ (Ó+Ó,€FØ�x‰x˜
Ó#€HÜ�(œD×!Ò!ä# HÓ-×9Ð9°ˆÜ$Ø�‰�Ó! ?°JÀdôL€Mä  §¡¨+Ó!6¸À\ÐY]Ô^€IßÜ# HÓ8ˆÜ
ˆ7×Ð�fÐTÔUÜ˜8Ô$Ü-¨cÓ<€HÜ	�—‘˜Ó!×	"Ô	"¡j rð �{‰{˜4Ó%ˆÜÐ$ d°'×2IÐ2I¸V×2IÐ2IÀr×1PÑ1PÓ1RÔSð%	#Ø×!Ñ!Ø &ÀHØ+¼^ÈCÓ=Pð "ó RˆBðJ �{‰{˜4Ó%ˆßð ×-Ñ-¨dÓ8ˆHßØŸ™Ñ"SÉ(Ó"SÓS�ÜØ)¨#¨Ð.QØ�hÐMðOóPð Pô �5·d˜4×2Ò2À÷ \ð \Ø(¨¨Ð-ZÐ[ô]à�m‰m˜DÓ&ˆô
 ˜3· s§v¢v¸$ð !#× 3Ñ 3°DÔ >ó @á >˜1ô ˜qÔ"4Ö5Ù >ñ @ôA÷} 
#Ò	"øð ×+Ñ+ô 
	ô ØMÈlÈ^ð \ð óô ÷! 
#Ò	"ûð* × Ñ ô 	^ô Ø+¨I¨;ð 7UØUXÐTYÐY[ð]ó^ô ^÷1 
#Ò	"ûð6 ×(Ñ(ô 		Lô ð+Ø+/¯9©9°X×5EÑ5EÓ+FÐ*Gð HJðKóLô L÷? 
#Ò	"ûðJ ×&Ñ&ô 	#ô Ø+¨I¨;ð 7!ð "ó#ô #÷Q 
#Ò	"ûðJ	#üò4 @÷ 
#×	"Ð	"ús°   Ä-MÅMÅI1Å=A>MÇ<A
MÉMÉMÉ1MÊJ ÊMÊMÊ MÊ3MÊ4KËMËMËMË(MË)'L ÌMÌMÌ MÌ3MÌ4MÍMÍMÍMÍMÍM0	c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   ,  s   € ÷ %=ñ %=˜ð %= sñ %=r&   c                óü  € \        RV 4      p\        \        V RR4      4      pV P                  R4      p\	        V P                  R4      4      ;_uu_ 4       w  rV\        VRJ ;'       g    WEP                  9   R\        VP                  4       R24       VP                  Wb4      p\        T;'       d    VP                  ;'       d
    V\        9  '       * R	\        \        4       R
V: R24       VP                  WbW4\        V4      R7      p\        VRV R24       VP                  Wb4      P                  p	RV	/p
VR8X  d   W”8w  d
   WJR&   RV
R&   \        WVVR3/ V
B uuRRR4       #   + '       g   i     R# ; i)z?Transition the task to blocked with a reason a human will read.rc   rf  u2   reason is required â€” explain what input you needÚkindrá   Nzkind must be one of z (or omit it)z,goal_mode tasks can only block with kind in z (got u‘   ). If the task is actually finished or cannot proceed for another reason, call kanban_complete instead â€” the completion judge will evaluate it.)rf  r÷  r…  zcould not block z% (unknown id or not in running/ready)Ú
block_kindrN  Úrequested_kindzÎkind='dependency' only waits on an incomplete parent; no parent is open, so this was recorded as needs_input (sticky until a human unblocks) instead of parking in todo where the dispatcher would respawn it.r„  rX  )rÛ   r
  r-  r9   rì   r~   ÚVALID_BLOCK_KINDSrž   rï   rg  Ú_GOAL_MODE_BLOCK_ALLOWED_KINDSÚ
block_taskrÌ   rø  r  )r“   r£   rÀ   rf  r÷  ré   rë   rð   rõ   Úlanded_kindrû   s   &,         r$   Ú_handle_blockrþ  +  st  € ô ˜¨Ó
-€CÜÜ�d˜HÐ&ZÓ[ó]€Fà�8‰8�FÓ€DÜ	�—‘˜Ó!×	"Ô	"¡j rÜˆt�tˆ|×;Ð;˜t×';Ñ';Ñ;Ø%¤f¨R×-AÑ-AÓ&BÐ%CÀ=ÐQô	Sð �{‰{˜4Ó%ˆÜ�D×ZÐZ˜TŸ^™^×ZÐZ°Ô<ZÑ0ZÔ[Ø=ÜÔ7Ó8Ð9¸À¹xð H8ð9ô	:ð
 �]‰]˜4¨VÔP^Ð_bÓPcˆ]ÓdˆÜˆrÐ% c UÐ*OÐPÔQØ—k‘k $Ó,×7Ñ7ˆØ# [Ð1ˆØ�<Ô KÔ$7à&*Ð"Ñ#ðTð �&‰Mô
 ˜" C¨Ñ<°eÑ<÷? 
#×	"×	"Ó	"ús   ÁA0E*ÃBE*Å*E;	c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   U  s   € ÷ Eñ E˜4ð E¨#ñ Er&   c           
     ó†  € \        RV 4      pV P                  R4      p\        VRJ ;'       g    \        V\        4      R4       V'       d0   VP                  4       '       d   \        VP                  4       4      MRp\        V P                  R4      4      ;_uu_ 4       w  rVVP                  Wb4      p\        T;'       d    VP                  '       * R\        \        4       R24       VP                  WbV\        V4      R7      p\        VR	V R
24       \        WVVRVR7      uuRRR4       #   + '       g   i     R# ; i)z8Park the current task until an orchestrator re-gates it.rd   rf  Nzreason must be a stringrá   zCgoal_mode tasks cannot be scheduled: use kanban_block with kind in z\ for a genuine external blocker, or kanban_complete so the completion judge can evaluate it.©rf  r…  zcould not schedule z2 (unknown id or not in todo/ready/running/blocked)Ú	scheduled)rf  )rÛ   r9   r~   r0   rC   r¹   r
  rì   rï   rg  rž   rû  Úschedule_taskrÌ   r  )	r“   r£   rÀ   Ú
raw_reasonrf  ré   rë   rð   rõ   s	   &,       r$   Ú_handle_scheduler  T  s  € ô Ð)¨4Ó
0€CØ—‘˜(Ó#€JÜ
ˆ:˜Ð×<Ð<¤¨J¼Ó!<Ð>WÔXß,6¸:×;KÑ;K×;MÒ;MŒW�Z×%Ñ%Ó'Ô(ÐSW€FÜ	�—‘˜Ó!×	"Ô	"¡j rð �{‰{˜4Ó%ˆÜ�D×+Ð+˜TŸ^™^Ô,ðÜÔ:Ó;Ð<ð =VðVô	Wð ×ÑØ˜f´nÀSÓ6Ið ó KˆäˆrÐ(¨¨Ð-_Ð`ÔaÜ˜" C¨¸VÔD÷ 
#×	"×	"Ó	"ús   ÂBD/Ä/E 	c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   j  s   € ÷ *3ñ *3 ð *3°ñ *3r&   c                ó´  € \        RV 4      p\        \        V RR4      4      pV P                  R4      p\	        V4       Ve   \        V4      p\        VRJR4       \        V P                  R4      RRR	R
7      pV'       d   \        WE4      p\        W$4      p\        V P                  R4      ;'       g    R4      pV'       d6   ^ RIHpHp \        V! V4      RV: RRP                  V! 4       4       24       \        V P                  R4      4      ;_uu_ 4       w  rš\!        RV	P#                  W¢4      W#4        V	P%                  W¢W4V\'        V4      R	R7      w  r¼\        TRT RT;'       g    R 24       \-        YšTR4      uuRRR4       #   T	P(                   d$   p\+        RT R24      u Rp?uuRRR4       # Rp?ii ; i  + '       g   i     R# ; i)z6Move implementation into the first-class review phase.re   rÚ  ui   summary is required â€” describe what was implemented and how it was verified so the reviewer has contextrÎ   Nz'metadata could not be safely serializedr   rß  TrÞ  Úreviewer)Úlist_profile_namesÚprofile_existszreviewer profile z' is not installed. Installed profiles: r™   rá   )rÚ  rÎ   r  r…  Úwith_reasonzAkanban_request_review could not preserve the declared artifacts: z´. Your task is still in-flight (no state change) and its scratch workspace was kept. Fix the artifact path or storage error, then retry kanban_request_review with the same handoff.zcould not request review for rš   z"unknown id or not in running/readyÚreview)rÛ   r
  r-  r9   r  r  r~   r  r*  rÓ   r  r‹   r	  r
  rŸ   rì   rr  rï   Úrequest_reviewrÌ   rå  r   r  )r“   r£   rÀ   rÚ  rÎ   r   r  r	  r
  ré   rë   rõ   Úfail_reasonrí  s   &,            r$   Ú_handle_request_reviewr  i  sß  € ô Ð/°Ó
6€CÜ”mØˆið 3ó4ó 5€Gð �x‰x˜
Ó#€HÜ˜8Ô$ØÒÜ# HÓ-ˆÜˆx˜tÐ#Ð%NÔOÜ  §¡¨+Ó!6¸À\ÐY]Ô^€IßÜ# HÓ8ˆÜ-¨cÓ<€Hä˜4Ÿ8™8 JÓ/×7Ð7°4Ó8€HßßJô 	‰~˜hÓ'Ø" 8¡,ð /&Ø&*§i¡iÑ0BÓ0DÓ&EÐ%FðHô	Iô 
�—‘˜Ó!×	"Ô	"¡j rÜÐ*¨B¯K©K¸Ó,BÀCÔQð	AØ ×/Ñ/Ø 7ÈÜ .¨sÓ 3Àð 0ó G‰OˆBô 	ˆrÐ2°3°%°rØ!×IÐIÐ%IÐJðLô 	Mä˜" C¨Ó2÷# 
#Ò	"øð ×+Ñ+ô 	Aô ØSÐT`ÐSað b?ð @óAô A÷ 
#Ò	"ûð	Aú÷ 
#×	"Ð	"úsB   ÄGÄ;!FÅGÅ/GÆGÆ F>Æ.GÆ/GÆ>GÇGÇG	c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   ˜  s   € ÷ 	Fñ 	F $ð 	F°ñ 	Fr&   c           
     ó`  € \        RV 4      p\        \        V RR4      4      p\        V P	                  R4      4      ;_uu_ 4       w  rEVP                  WRV\        V4      R7      w  rg\        TRT RT;'       g    R 24       \        WEVR	VR
7      uuRRR4       #   + '       g   i     R# ; i)z8Return a reviewer-owned running task to its implementer.rf   rf  u2   reason is required â€” describe the changes neededrá   r  zcould not request changes for rš   zinvalid review stateÚready)ÚimplementerN)	rÛ   r
  r-  rì   r9   Úrequest_changesrÌ   r~   r  )r“   r£   rÀ   rf  ré   rë   rõ   rò  s   &,      r$   Ú_handle_request_changesr  —  s¤   € ô Ð0°$Ó
7€CÜÜ�d˜HÐ&ZÓ[ó]€Fä	�—‘˜Ó!×	"Ô	"¡j rØ×'Ñ'Ø˜f´nÀSÓ6Ið (ó K‰
ˆäˆrÐ3°C°5¸¸6×;[Ð;[ÐE[Ð:\Ð]Ô^Ü˜" C¨¸fÔE÷	 
#×	"×	"Ó	"ús   ÁABÂB-	Úkanban_heartbeatc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   ¥  s   € ÷  ñ  ˜Dð  ¨3ñ  r&   c           
     óœ  € \        RV 4      p^ RIHp \        V P	                  R4      4      ;_uu_ 4       w  rEVP                  WR\        P                  P	                  R4      R7       VP                  WRV P	                  R4      \        V4      R7      p\        VRV R	24       \        VR
7      uuRRR4       #   + '       g   i     R# ; i)z¸Signal liveness: extend the claim TTL AND record a heartbeat event.
Without the claim half, a worker blocked in one long tool call would still
be reclaimed by ``release_stale_claims``.r  rw  rá   rƒ  )r‚  r„  )r„  r…  zcould not heartbeat z (unknown id or not running))r¿   N)rÛ   ræ   rx  rì   r9   r‰  rW   rX   rŠ  rÌ   r~   rø   )r“   r£   rÀ   r}  ré   rë   rõ   s   &,     r$   Ú_handle_heartbeatr  ¤  s¦   € ô
 Ð*¨DÓ
1€CÝ4Ü	�—‘˜Ó!×	"Ô	"¡j rð 	×Ñ˜4¬b¯j©j¯n©nÐ=WÓ.XÐÔYØ×!Ñ!Ø˜DŸH™H VÓ,¼nÈSÓ>Qð "ó SˆäˆrÐ)¨#¨Ð.JÐKÔLÜ˜3Ô÷ 
#×	"×	"Ó	"ús   µA:B:Â:C	Úkanban_commentc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   ¶  s   € ÷ 0ñ 0˜$ð 0¨ñ 0r&   c           
     óv  € \        R4       V P                  R4      pV'       g   \        R4      h\        \	        V R4      4      p\        4       p\        V P                  R4      4      ;_uu_ 4       w  rVVP                  WbV\        V4      R7      p\        W'R7      uuRRR4       #   + '       g   i     R# ; i)	z$Append a comment to a task's thread.r  r¿   z¬task_id is required: comments are per-task and this session has no dispatcher-assigned task to default to. Discover task ids with kanban_list, or pass the task id you mean.ri  rá   )r¨  ri  )r¿   Ú
comment_idN)
r´   r9   rh   r
  r-  rŒ   rì   Úadd_commentrC   rø   )r“   r£   rÀ   ri  r¨  ré   rë   Úcids   &,      r$   Ú_handle_commentr   µ  s–   € ô %Ð%5Ô6Ø
�(‰(�9Ó
€Cßô ð9ó:ð 	:ô ”=  vÓ.Ó/€Dô !Ó"€FÜ	�—‘˜Ó!×	"Ô	"¡j rØ�n‰n˜T¨v¼CÀ»IˆnÓFˆÜ˜3Ô/÷ 
#×	"×	"Ó	"ús   Á1+B'Â'B8	c               ó   € V ^8„  d   QhRR/# r†   r"   )r#   s   "r$   r%   r%   Ð  s   € ÷ Fñ FÀ3ñ Fr&   c                óÖ   € \        V 4      ;_uu_ 4       w  rVVP                  Wa\        V4      VVRV R7      p\        W\	        V4      R7      uuRRR4       #   + '       g   i     R# ; i)z”Store via ``kanban_db.store_attachment_bytes`` (shared size cap, per-task
dir, metadata row) so agent, dashboard, and CLI surfaces stay in lockstep.rG   )Úcontent_typeÚuploaded_byrá   )r¿   Úattachment_idÚsizeN)rì   Ústore_attachment_bytesrC   rø   rL  )rá   rÀ   ÚfilenameÚdatar#  ré   rë   Úatt_ids   &&&&&   r$   Ú_store_attachmentr+  Ð  sU   € ô 
��Œ™*˜2Ø×*Ñ*Ø”s˜8“} dØ%°7À%ð +ó Iˆô ˜3¼3¸t»9ÔE÷	 
��‹ús   ”8AÁA(	Úkanban_attachc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   Û  s   € ÷ _ñ _˜ð _¨ñ _r&   c           	     óD  € \        RV 4      p\        V R4      p\        V R4      p^ RIp^ RIp VP	                  \        V4      RR7      p\        T P                  R4      Y#YpP                  R	4      4      #   TP                  \        3 d   p\        RT 24      hRp?ii ; i)
z)Attach an inline (base64) file to a task.r,  r(  Úcontent_base64NT)Úvalidatez$content_base64 is not valid base64: rá   r#  )rÛ   r-  Úbase64ÚbinasciiÚ	b64decoderC   ÚErrorr    rh   r+  r9   )	r“   r£   rÀ   r(  Úcontent_b64r1  r2  r)  r¦   s	   &,       r$   Ú_handle_attachr6  Ú  s¢   € ô ˜¨Ó
.€CÜ˜T :Ó.€HÜ Ð&6Ó7€KÛÛðBØ×Ñ¤ KÓ 0¸4ÐÓ@ˆô ˜TŸX™X gÓ.°¸tÇXÁXÈnÓE]Ó^Ð^øð �N‰NœJÐ'ô BÜÐ<¸Q¸CÐ@ÓAÐAûðBús   ®A5 Á5BÂBÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚurlrC   Ú	max_bytesrÊ   r    ztuple[bytes, Optional[str]]r"   )r#   s   "r$   r%   r%   ì  s"   € ÷ #;ñ #; ð #;°ð #;Ð8Sñ #;r&   c           	     ó  € ^ RI HpHp ^ RIp^ RIHp T p\        \        ^,           4       EF°  pV! V4      P                  ;'       g    RP                  4       pVR9  d   \        RV: R24      hV! V4      '       g   \        RV 24      h. p	^ p
VP                  RVR	R
/^RR7      ;_uu_ 4       pVP                  '       dE   VP                  P                  R4      pV'       g   \        RV 24      hV! Wl4      p RRR4       KÜ  VP                  4        VP                  P                  R4      ;'       g    RP!                  R4      ^ ,          P#                  4       ;'       g    RpVP%                  R4       FB  pV
\'        V4      ,          p
W¡8”  d   \        RVR,           R24      hV	P)                  V4       KD  	  RRR4       RP+                  V	4      X3u # 	  \        RV  24      h  + '       g   i     L5; i)a†  Fetch ``url`` over http(s) capped at ``max_bytes`` -> ``(data, content_type)``.
Every hop is SSRF-checked (redirects followed manually) so a model-controlled URL, or a
public host 302ing, cannot reach loopback/private/cloud-metadata ranges. ``ValueError``
for bad scheme, blocked target, too many redirects, or a body over the cap (checked
while streaming, so nothing oversize is buffered).)ÚurljoinÚurlparseN)Úis_safe_urlr`  zunsupported URL scheme z; only http/https are allowedz;URL blocked by SSRF protection (private/internal address): ÚGETz
User-Agentzhermes-kanban/attachF)ÚheadersÚtimeoutÚfollow_redirectsÚlocationz&redirect without Location header from zcontent-typeÚ;zattachment exceeds z	 MB limitr&   ztoo many redirects fetching )ÚhttpÚhttpsi   )Úurllib.parser;  r<  ÚhttpxÚtools.url_safetyr=  ÚrangeÚ_MAX_ATTACH_URL_REDIRECTSÚschemer7  r    ÚstreamÚis_redirectr?  r9   Úraise_for_statusÚsplitr¹   Ú
iter_bytesrL  ÚappendrŸ   )r8  r9  r;  r<  rG  r=  Úcurrent_urlrn  rK  ÚchunksÚtotalÚresprB  r#  Úchunks   &&             r$   Ú_download_url_with_caprW  ì  sâ  € ÷ /ÛÝ,Ø€KÜÔ,¨qÕ0×1ˆÙ˜;Ó'×.Ñ.×4Ð4°"×;Ñ;Ó=ˆØÐ*Ô*ÜÐ6°v±jÐ@]Ð^Ó_Ð_Ù˜;×'Ò'ÜØMÈkÈ]Ð[ó]ð ]à ˆØˆØ�\‰\˜% °|ÐE[Ð6\Ø"$°uð ÷ >ô >ØAEØ××ÐØŸ<™<×+Ñ+¨JÓ7�ßÜ$Ð'MÈkÈ]Ð%[Ó\Ð\Ù% kÓ<�Ø÷>ñ >ð ×!Ñ!Ô#Ø ŸL™L×,Ñ,¨^Ó<×BÐBÀ×IÑIÈ#ÓNÈqÕQ×WÑWÓY×aÐaÐ]aˆLØŸ™¨Ö5�Øœ˜U›Õ#�ØÔ$Ü$Ð':¸9ÈÕ;UÐ:VÐV_Ð%`ÓaÐaØ—‘˜eÖ$ñ	 6÷>ð �x‰x˜Ó Ð-Ò-ñ1 2ô2 Ð3°C°5Ð9Ó
:Ð:÷!>÷ >ús%   Â05G.Ã&G.Ä1G.Ä9-G.Å'AG.Ç.G>c               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%     s   € ÷ Xñ X˜Tð X¨Cñ Xr&   c           	     ó  € ^ RI Hp \        RV 4      p\        \	        V R4      4      P                  4       pV P                  R4      ;'       g    V P                  R4      pV'       d    \        V4      P                  4       '       gP   ^ RIHpH	p V! V! V4      P                  P                  R^4      R,          4      P                  4       ;'       g    Rp \        WBP                  4      w  r‰\'        T P                  R4      Y5Y€P                  R4      ;'       g    T	4      #   \         d   p
\        R	T
 24      u R
p
?
# R
p
?
i\          d1   p
\"        P%                  R4       \        RT RT
 24      u R
p
?
# R
p
?
ii ; i)zHAttach a file fetched server-side from an http(s) URL (shared size cap).rã   r‚   r8  r(  rƒ   )Úunquoter<  Ú/Údownloadzkanban_attach_url: Nz!kanban_attach_url download failedz#kanban_attach_url: failed to fetch rš   rá   r#  éÿÿÿÿ)ræ   rä   rÛ   rC   r-  r¹   r9   rF  rZ  r<  ÚpathÚrsplitrW  ÚKANBAN_ATTACHMENT_MAX_BYTESr    r   r=   r¡   r¢   r+  )r“   r£   ré   rÀ   r8  r(  rZ  r<  r)  Ú
fetched_ctr¦   s   &,         r$   Ú_handle_attach_urlrb    s?  € õ +Ü
Ð+¨TÓ
2€CÜ
Œm˜D %Ó(Ó
)×
/Ñ
/Ó
1€CØ�x‰x˜
Ó#×8Ð8 t§x¡x°Ó'8€Hßœ3˜x›=×.Ñ.×0Ò0ç2Ù™8 C›=×-Ñ-×4Ñ4°S¸!Ó<¸RÕ@ÓA×GÑGÓI×WÐWÈZˆðLÜ1°#×7UÑ7UÓVÑˆô Ø�‰�Ó˜3¨$·±¸Ó0H×0VÐ0VÈJóXð Xøô ô 5ÜÐ/°¨sÐ3Ó4Õ4ûÜô LÜ×ÑÐ<Ô=ÜÐ?À¸uÀBÀqÀcÐJÓKÕKûðLús6   ÃD# Ä#E?Ä.EÄ;E?ÅE?ÅE?Å%E:Å4E?Å:E?Úkanban_attachmentsc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   )  s   € ÷ Zñ Z˜dð Z¨Sñ Zr&   c                óR  € \        V 4      p\        V P                  R4      4      ;_uu_ 4       w  r4\        W4V4       \        P
                  ! RRRTRVP                  WB4       Uu. uF  p\        V\        4      NK  	  up/4      uuRRR4       # u upi   + '       g   i     R# ; i)z@List a task's attachments (read-only; no ownership restriction).rá   rõ   Tr¿   rã  N)	rÁ   rì   r9   rñ   rö   r÷   rë  rB  rì  )r“   r£   rÀ   ré   rë   ró  s   &,    r$   Ú_handle_attachmentsrf  (  s–   € ô ˜4Ó
 €CÜ	�—‘˜Ó!×	"Ô	"¡j rÜ�r Ô%Ü�zŠzØ�$˜	 3ØØ8:×8KÑ8KÈDÔ8VóXÙ8V°1”˜Ô-Ö.Ñ8VñXðYó Z÷ 
#Ò	"ùòX÷	 
#×	"Ð	"ús   ®7BÁ%BÁ>BÂBÂB&	c               ó    € V ^8„  d   QhRRRR/# )r   r€   r·   r    r"   )r#   s   "r$   r%   r%   4  s   € ÷ ñ  mð ¸ñ r&   c                ó2  € V '       g   R#  ^ RI Hp ^ RIHp V! V! 4       R,          RR7      p TP                  T 4      '       d   T MR TP                  4        #   \         d    \
        P                  RRR7        R# i ; i  TP                  4        i ; i)	zGReturn a session id only when it is present in this profile's state.db.N)Ú	SessionDB)Úget_hermes_homeústate.dbT)Údb_pathÚ	read_onlyz3Could not open state.db to verify Kanban provenancerc  )	Úhermes_stateri  Úhermes_constantsrj  r=   r¡   r|  Úget_sessionrè   )r€   ri  rj  Ústates   &   r$   Ú_persisted_session_idrr  4  s   € çÙðÝ*Ý4á¡/Ó"3°jÕ"@ÈDÔQˆðØ"×.Ñ.¨z×:Ò:‰zÀÐDà�‰�øô ô Ü�‰ÐJÐUYˆÔZÚðûð 	�‰�ús"   Œ"A ¯B ÁB Á"BÂ BÂBc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   G  s   € ÷ ;Dñ ;D˜ð ;D¨ñ ;Dr&   c                óD  € \        R4       \        V R4      pV P                  R4      p\        VR4       V P                  R4      V P                  R4      rTRV 9   d
   V R,          MV P                  R4      pR	p\	        V R
4      \        V P                  R4      RR4      \	        V R4      r©pV P                  R4      V P                  R4      rË\        T;'       g    V'       * R4       \        V P                  R4      ;'       g    . RR4      p\        V P                  R4      4      ;_uu_ 4       w  rï^ RIHp ^ RI	H
p \        4       '       d    \        P                  P                  R4      MR	pV'       d   VP                  VV4      MR	p\        V P                  R4      4      ;'       gI    V'       d   VP                   MR	;'       g+    \        V! 4       4      ;'       g    \        V! RR4      4      pVf6   Vf2   Vf.   Ve*   VP"                  '       d   VP"                  VP$                  rvTP'                  T\)        V4      P+                  4       V P                  R4      \)        V4      \-        V4      V P                  R4      ;'       g     \        P                  P                  R4      \/        V P                  R4      ^ 4      YETV P                  R4      YxTV P                  R4      \/        V P                  R4      4      T	Y¼T
\/        V P                  R 4      4      V P                  R!4      \)        V P                  R"4      ;'       g    R#4      \1        4       VR$7      p\3        VP                  VV4      \4        4      pVP7                  VV4       Uu. uF  pVP8                  R%8X  g   K  VNK  	  ppV'       d   R&R'R(VR-,          P:                  R),          /MR&R*/p\=        R.R+V/VBVBR,\?        VV4      /B uuR	R	R	4       # u upi   + '       g   i     R	# ; i)/z@Create a (child) task; orchestrator workers use this to fan out.r   rƒ   rÉ  u   assignee is required â€” name the profile that should execute this task (the dispatcher will only spawn tasks with an assignee)Úworkspace_kindÚworkspace_pathÚprojectr�   NÚtriageÚskillszskill namesrg  rV  Úproviderz-'provider' requires 'model' to be set as wellrE  rÝ  rá   ©Úget_session_env)Ú_current_origin_session_idrV   r€   rÑ   r`  ri  rÊ  ÚHERMES_TENANTÚpriorityÚidempotency_keyÚmax_runtime_secondsÚgoal_max_turnsÚcompletion_contractÚinitial_statusÚrunning)rƒ   ri  rÉ  rE  rÊ  r  ru  rv  r�   rá   Úproject_source_task_idrx  Úcreator_task_idr€  r�  ry  Úmodel_overrideÚprovider_overriderg  r‚  rƒ  r„  Ú
created_byr€   Údependency_waitÚgatedTÚgated_byÚparentFr¿   Ú
subscribedr]  r"   ) r´   r-  r9   r~   r9  r  rì   Úgateway.session_contextr|  Útools.async_delegationr}  rR   rW   rX   rï   rr  r€   r�   r   Úcreate_taskrC   r¹   r  r<  rŒ   rB  Ú_CREATED_FIELDSr¼  r÷  Úpayloadrø   Ú_maybe_auto_subscribe)r“   r£   rƒ   rÉ  ru  rv  r�   r†  rx  ry  rg  rˆ  r‰  rE  ré   rë   r|  r}  Úself_tidÚ	self_taskr€   Únew_tidr  r¦   ÚwaitÚgates   &,                        r$   Ú_handle_creater›  F  sž  € ô % _Ô5Ü˜$ Ó(€EØ�x‰x˜
Ó#€HÜ
ˆ8ð Tô Uð &*§X¡XÐ.>Ó%?ÀÇÁÐJZÓA[�Nà$-°Ô$5��i–¸4¿8¹8ÀLÓ;Q€JØ!Ðä˜˜hÓ'Ô)9¸$¿(¹(À8Ó:LÈhÐXeÓ)fÜ˜˜kÓ*ð €Fð )-¯©°Ó(9¸4¿8¹8ÀJÓ;OÐ%Ü
ˆ>×2Ð2Ð!2Ô2Ð4cÔdÜ˜tŸx™x¨	Ó2×8Ð8°b¸)ÀZÓP€GÜ	�—‘˜Ó!×	"Ô	"¡j rÝ;ÝEä2×4Ò4ô —J‘J—N‘NÐ#7Ô8Ø:>ð 	ç3;�B—K‘K  hÔ/Àˆ	ô
 ,¨D¯H©H°\Ó,BÓC÷ Yð Yß2;˜)×.Ò.À÷Yð Yä.Ñ/IÓ/KÓL÷Yð Yô /©Ð?RÐTVÓ/WÓXð 	ð Ò .Ò"8¸^Ò=SØÒ$¨×)=×)=Ð)=Ø5>×5IÑ5IÈ9Ï<É<Ð2Ø—.‘.Øœ˜E›
×(Ñ(Ó*°·±¸&Ó1AÌCÐPXËMÜ˜'“N¨4¯8©8°HÓ+=×+`Ð+`ÄÇÁÇÁÐP_ÓA`Ü˜dŸh™h zÓ2°AÓ6Ø)ÐU_ð —(‘(˜7Ó#Ø#9Ø$Ø ŸH™HÐ%6Ó7Ü (¨¯©Ð2GÓ)HÓ IÐRXØ)Ø´¸¿¹ÐBRÓ9SÓ0TØ $§¡Ð)>Ó ?Ü˜tŸx™xÐ(8Ó9×FÐF¸YÓGÜ*Ó,¸ð! !ó Eˆô" ˜Ÿ™ T¨7Ó3´_ÓEˆØŸ>™>¨$°Ô8ÓXÑ8�a¸A¿F¹FÐFWÑ<W—�Ñ8ˆÐXßJN�˜˜z¨4°­8×+;Ñ+;¸HÕ+EÑFÐU\Ð^cÐTdˆÜñ D˜7ð D fð D°ñ DÜ3°D¸'ÓBòD÷K 
#Ò	"ùòF Y÷G 
#×	"Ð	"úsK   Ä0APÅ84PÆ-PÆ6PÇPÇ#4PÈF PÎP	Î0P	Î6APÐ	PÐP	c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úsession_keyrC   Úprofiler·   r    r"   )r#   s   "r$   r%   r%   …  s!   € ÷ ñ  sð °]ð Àsñ r&   c                óZ  € RpV'       d:   VR8w  d3    ^ RI Hp ^ RIHpHp V! V4      '       d   V! V! V4      4      R,          p ^ RIHpHp V! V4      p VP                  V 4      ;'       g    T  V! V4       #   \
         d    Rp LEi ; i  T! T4       i ; i  \
         d    T u # i ; i)až  Re-resolve a TUI session key at subscribe time: the inherited ``HERMES_SESSION_KEY``
can name a session already superseded by a compaction fork, and a subscription bound to
the dead key silently drops every later completion notification (#110068). Maps the key
to its continuation tip via the session store's lineage walk. Best-effort, fail-open:
any error (or an unresolvable key) returns *session_key* unchanged.NrD   )ÚPath)Úget_profile_dirr
  rk  )ÚacquireÚrelease_or_close)
Úpathlibr   r‹   r¡  r
  r=   Úhermes_state_registryr¢  r£  Úresolve_resume_session_id)	r�  rž  rl  r   r¡  r
  r¢  r£  Údbs	   &&       r$   Ú_live_tui_session_keyr¨  …  sª   € ð €Gß�7˜iÔ'ð	Ý$ßKÙ˜g×&Ò&Ù™¨wÓ7Ó8¸:ÕE�ðßCÙ�WÓˆð	!Ø×/Ñ/°Ó<×KÐKÀÐKá˜RÕ øô ô 	ØŠGð	ûñ ˜RÕ ûÜô ØÒðúsF   “A: ¯A: ÁB ÁB Á.B Á1B Á:B
Â	B
Â
BÂB ÂB*Â)B*c               ó   € V ^8„  d   QhRR/# )r   r    zOptional[dict[str, Any]]r"   )r#   s   "r$   r%   r%   Ÿ  s   € ÷ +5ñ +5Ð 8ñ +5r&   c                 ó–  € ^ RI Hp  V ! RR4      V ! RR4      r!V'       d	   V'       g?   V ! RR4      ;'       g!    \        P                  P	                  RR4      pV'       g   R# RTr!V ! RR4      ;'       g    RpV ! R	R4      ;'       g    RpV ! R
R4      ;'       g    RpV ! RR4      pV'       g   ^ RIHp V! R4      pVR8X  d   \        W'4      pRV3RV3RV ! RR4      3RV ! RR4      33 U	U
u/ uF  w  ršV
'       g   K  WšbK  	  pp	p
VP                  4       R8X  da   V'       dY   T;'       g    RP                  4       R9   d:   RVR&   \        V4      R9  d   \        V4      VR&   V'       d   \        V4      VR&   \        YYEV ! RR4      ;'       g    RV ! RR4      ;'       g    RTVR8w  d   RMRT;'       g    RR7	      # u up
p	i )až  ``kanban_db.add_notify_sub`` kwargs for the calling session, or None (CLI/cron/tests).
Gateway sessions: ``HERMES_SESSION_PLATFORM``/``CHAT_ID`` ContextVars. TUI/desktop:
those are cleared but the subprocess inherits ``HERMES_SESSION_KEY`` -> ``platform="tui"``
for the TUI poller. ``HERMES_SESSION_ID`` is deliberately NOT a fallback: it is set for
every CLI/ACP invocation and would auto-subscribe every CLI run.r{  ÚHERMES_SESSION_PLATFORMr`  ÚHERMES_SESSION_CHAT_IDÚHERMES_SESSION_KEYNÚtuiÚHERMES_SESSION_CHAT_TYPEÚHERMES_SESSION_THREAD_IDÚHERMES_SESSION_MESSAGE_IDÚHERMES_SESSION_PROFILErˆ   rD   Ú	thread_idÚ	chat_typeÚscope_idÚHERMES_SESSION_SCOPE_IDÚparent_chat_idÚHERMES_SESSION_PARENT_CHAT_IDÚtelegramTÚ telegram_dm_topic_reply_fallbackÚdirect_messages_topic_idÚtelegram_reply_to_message_idÚHERMES_SESSION_USER_IDÚHERMES_SESSION_USER_ID_ALTznotify+wake)	r3   Úchat_idr´  r³  Úuser_idÚuser_id_altÚnotifier_profileÚdelivery_modeÚdelivery_metadata>   ÚdmÚdirectÚprivate>   r`  r/  )r�  r|  rW   rX   r9   r‹   r‰   r¨  r7  rC   r”   )Úenvr3   r¿  r�  r´  r³  Ú
message_idrÂ  r‰   ÚkÚvrÄ  s               r$   Ú_resolve_notify_targetrÌ  Ÿ  sè  € õ ?ÙÐ5°rÓ:¹CÐ@XÐZ\Ó<]ˆgßŸ7ÙÐ.°Ó3×_Ð_´r·z±z·~±~ÐFZÐ\^Ó7_ˆßÙØ! ;�'ÙÐ.°Ó3×;Ð;°t€IÙÐ.°Ó3×;Ð;°t€IÙÐ0°"Ó5×;Ð;¸€JÙÐ3°RÓ8ÐßÝ<Ù/°	Ó:ÐØ�5Ôô (¨ÓBˆð ˜)Ð$ {°IÐ&>Ø™Ð6¸Ó;Ð<Ø™sÐ#BÀBÓGÐHñ
ô)ñ
‘�ô ô	 	ˆŠñ 
ð ñ )ð 	�‰Ó˜JÔ&¯9Ø—�˜b×'Ñ'Ó)Ð-HÔHØ@DÐÐ<Ñ=Üˆy‹> Ô*Ü<?À	»NÐÐ8Ñ9ßÜ@CÀJÃÐÐ<Ñ=ÜØ°iÙÐ,¨bÓ1×9Ð9°TÙÐ4°bÓ9×AÐA¸TØ)Ø'/°5Ô'8‘m¸dØ+×3Ð3¨tô5ð 5ùó)s   Ã/GÄ Gc               ó$   € V ^8„  d   QhRRRRRR/# )r   rë   r   r¿   rC   r    r!   r"   )r#   s   "r$   r%   r%   Í  s!   € ÷ ñ  ð ¨cð °dñ r&   c           
     ó@  a€  \        \        4       RRRR7      '       g   R#  Ro \        4       oSf   R# ^ RIHp \        ;QJ d.    V3R lVP                  W4       4       F  '       g   K   RM#	  RM! V3R lVP                  W4       4       4      '       d   R# VP                  ! V 3R	V/SB  R#   \         d     L�i ; i  \         dO   p\        P                  R
TS'       d
   SR,          MR\        S;'       d
    SR,          4      4        Rp?R# Rp?ii ; i)aF  Subscribe the calling session to completion/block events; True iff a row was
written (surfaced as ``subscribed`` so an orchestrator can fall back to explicit
``kanban_notify-subscribe``). Gated by ``kanban.auto_subscribe_on_create`` (default
True). Failures are logged and swallowed: bookkeeping must never fail kanban_create.r*   Úauto_subscribe_on_createTr   FN)Úkanban_db_notifyc              3  óÞ   <"  € T Fb  pVR ,          SR ,          8H  ;'       dC    VR,          SR,          8H  ;'       d(    VR,          ;'       g    RSR,          ;'       g    R8H  x € Kd  	  R# 5i)r3   r¿  r³  r`  Nr"   )r2   ÚsubÚtargets   & €r$   r6   Ú(_maybe_auto_subscribe.<locals>.<genexpr>ß  sx   øé € ð @á>�3ð �:� &¨Õ"4Ñ4÷ Kð K¸¸Y½È6ÐR[ÕK\Ñ9\÷ Kð KØ˜Õ$×*Ð*¨°°{Õ0C×0IÐ0IÀrÑJôKã>ùs   ƒA-¢A-½A-ÁA-Á A-r¿   z9_maybe_auto_subscribe failed: %r (platform=%r key_set=%r)r3   r`  r¿  )r   r   r=   rÌ  ræ   rÐ  r;   Úlist_notify_subsÚadd_notify_subr¡   rj  r!   )rë   r¿   Ú_kbnÚ_excrÓ  s   &&  @r$   r•  r•  Í  s  ø€ ð
Ü”{“} hÐ0JÐTX×YÓYÙð Zð €FðÜ'Ó)ˆØŠ>ÙÝ7÷ ‹3ô @à×/Ñ/°Ô>ó@�3�3Š3ô @à×/Ñ/°Ô>ó@÷ @ò @ñ Ø×Ò˜DÑ<¨'Ð<°VÒ<Ùøô ô Ùðûô  ô Ü�‰ØGØ¯�&˜Ö$°B¼¸V×=YÐ=YÈÈyÕHYÓ8Zô	\õ ûð	úsE   ƒB3 ¦C ¶C Á#C Á-,C ÂC Â3CÃ CÃDÃ0DÄ DÄDÚkanban_unblockc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   í  s   € ÷ 
Pñ 
P˜$ð 
P¨ñ 
Pr&   c                ó¤  € \        R4       \        R4       V P                  R4      p\        VR4       \	        V4      p\        V4       \        V P                  R4      4      ;_uu_ 4       w  r4\        VP                  WB4      RV R24       \        RRV/\        VP                  WB4      R	4      B uuRRR4       #   + '       g   i     R# ; i)
zFTransition a blocked task to ready, or todo while parents remain open.rÙ  r¿   ztask_id is requiredrá   zcould not unblock z (not blocked or unknown)Nr"   )rþ   )r´   rÞ   r9   r~   rC   r×   rì   Úunblock_taskrø   rB  rï   )r“   r£   rÀ   ré   rë   s   &,   r$   Ú_handle_unblockrÝ  ì  s¥   € ô %Ð%5Ô6ÜÐ/Ô0Ø
�(‰(�9Ó
€CÜ
ˆ3Ð%Ô&Ü
ˆc‹(€CÜ" 3Ô'Ü	�—‘˜Ó!×	"Ô	"¡j rÜˆr�‰˜tÓ)Ð-?À¸uÐD]Ð+^Ô_ÜÑO˜3ÐO¤'¨"¯+©+°dÓ*@À+Ó"NÑO÷ 
#×	"×	"Ó	"ús   Á,AB>Â>C	Úkanban_linkc               ó    € V ^8„  d   QhRRRR/# r’   r"   )r#   s   "r$   r%   r%   û  s   € ÷ Añ A�tð A cñ Ar&   c                ó”  € \        R4       V P                  R4      pV P                  R4      p\        T;'       d    TR4       \        V P                  R4      4      ;_uu_ 4       w  rEVP	                  WRV\        \        V4      4      R7      p\        R
RVRVRV/V'       d   RV/M/ B uuR	R	R	4       #   + '       g   i     R	# ; i)uÜ   Add a parentâ†’child dependency edge after the fact (cycles/self-links/running
children â†’ ValueError). A worker linking its OWN running card proves ownership
with its run id so the dependency-block handoff still works.rÞ  Ú	parent_idÚchild_idz(both parent_id and child_id are requiredrá   )rá  râ  Úexpected_child_run_idrŒ  r�  Nr"   )r´   r9   r~   rì   Ú
link_tasksrÌ   rC   rø   )r“   r£   rá  râ  ré   rë   rŒ  s   &,     r$   Ú_handle_linkrå  ú  s¼   € ô
 % ]Ô3Ø—‘˜Ó%€IØ�x‰x˜
Ó#€HÜ
ˆ9×!Ð!˜Ð#MÔNÜ	�—‘˜Ó!×	"Ô	"¡j rØ—‘Ø°Ü"0´°X³Ó"?ð ó Aˆô ñ A˜Yð A°ð AÀð Aß16�z 9Ñ-¸BñA÷	 
#×	"×	"Ó	"ús   Á&AB6Â6C	u   ðŸ“‹u   âœ”u   â�¸u   â�°u   ðŸ‘€u   â†©u   ðŸ’“u   ðŸ’¬u   ðŸ“Žu   âž•u   â–¶u   ðŸ”—r*   )r  ÚtoolsetÚschemaÚhandlerÚemojiÚcheck_fn>   rc   rb   rd   re   rf   rm   )r¨  ri  Ú
created_at)r÷  r”  rë  rý   )rþ   ru  rv  r�   )ŒÚ__conditional_annotations__rw   Ú
__future__r   rª   rö   ÚloggingrW   r†  Ú
contextlibr   Útypingr   r   r   Úagent.redactr   Úhermes_cli.goalsr   Útools.registryr	   r
   r   Úhermes_cli.configr   r   Útools.kanban_tools_schemasr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Ú	getLoggerrs   r¡   rÐ  rÒ  r@   rI   rN   rR   rZ   r^   ra   r�   rÚ   r=   rh   r~   r„   Ú__annotations__rŒ   r®   r´   r¼   rÁ   rÅ   rÌ   rÓ   r×   rÛ   rÞ   rì   rñ   rø   r  r
  r  r  r  r  r*  r-  r6  r9  r<  r  rO  r¹  rK  r¿  r»  r½  rì  r“  rB  rM  rû  rW  rk  rr  rˆ  rt  rŒ  r  r“  r¥  r”  r•  r®  rÃ  r×  rô  rþ  r  r  r  r  r   r+  r6  rJ  rW  rb  rf  rr  r›  r¨  rÌ  r•  rÝ  rå  Ú_ORCHESTRATOR_TOOLSÚ_TOOLSÚ_nameÚ_schÚ_handlerÚ_emojiÚ_gateÚregister)rì  s   @r$   Ú<module>r      sÙ  øðôõ #ã Û Û Û 	Û Ý %ß *Ñ *å .Ý 'ß BÑ Bß 2÷G÷ G÷ G÷ Gñ Gð 
×	Ò	˜8Ó	$€àÐ ØÐ õ
õ6õ@õGõ)ð ô(ó ð(ð
 ô)ó ð)ñ !ò "ó Ð ô
.ˆiô .õð ‘Y ¨lÐ;Ó<à™ G 9Ó-ð/Ð Ð+ó õ6õõ4Lõõ(Uõ,\õõ]õbõ  õFLð ð¸ö ó ðõ"õ.õLõ9õ.õðÈ÷ õNõ
÷ð �t˜S $¨¨t°W¸eÀSÈ%ÐQUÐW\Ð]€õ÷8ñ ð?ç?D¹u»wóH€ñ ðYßY^ÑY^ÓY`óbÐ ñ ÐZ×`Ñ`ÓbÓc€Ø2€Ø;€ÙØF×LÑLÓNóPÐ àN€õLõ
Dñ "+¨L¸-Ð+HÓ!IÐ õ	.ð ØðWð 	ðWðYð ØðOàð:ð<ð=Ð õ&Vðj (,Ð $Ø&)Ð ˜eÓ )Ø$Ð õõ$,ðd &)Ð "Ø$'Ð ˜EÓ 'Ø%'Ð �NÓ 'õ(ñZ �ÓôCó  ðCñ@ �Óô#ó  ð#ñ: Ð"Ó#ôRAó $ðRAñj �Ó ô%=ó !ð%=ñP Ð"Ó#ôEó $ðEñ( Ð(Ó)ô*3ó *ð*3ñZ Ð)Ó*ô	Fó +ð	Fñ Ð#Ó$ô ó %ð ñ  Ð!Ó"ô0ó #ð0õ4Fñ �Ó!ô_ó "ð_ð Ð õ#;ñL Ð$Ó%ôXó &ðXñ* Ð%Ó&ôZó 'ðZõñ$ �Ó!ô;Dó "ð;Dõ|õ4+5õ\ñ> Ð!Ó"ô
Pó #ð
Pñ �ÓôAó  ðAñ&   Ð0@Ð AÓBÐ àÐ&¨°fÐ=ØÐ&¨°fÐ=ØÐ.Ð0@À%ÐHØÐ(¨-¸Ð?ØÐ.Ð0@À%ÐHØÐ:Ð<RÐTZÐ[ØÐ<Ð>UÐW\Ð]ØÐ0Ð2CÀVÐLØÐ,¨o¸vÐFØÐ*¨N¸FÐCØÐ2Ð4FÈÐOØÐ4Ð6IÈ6ÐRØÐ*¨N¸EÐBØÐ,¨o¸uÐEØÐ&¨°fÐ=ð
?€ó" &,Ñ!€Eˆ4�˜6Ø/4Ð8KÔ/KÑ+ÐQc€EØ×Ó˜5¨(¸4ÈÐY_Ø$÷&ó &,r&   