Ë
    áß²j™  ã                  óF  — U d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
mZmZmZ  edd¬	«      Zd
ed<    edd¬	«      Zd
ed<   dZdZded<   ed d!d„«       Zd"d„Zd#d„Zd$d„Zed%d„«       Zd"d„Zd&d„Zd"d„Zd&d„Zd'd„Zd(d„Zed)d„«       Zed d*d„«       Z	 d 	 	 	 d+d„Zy),aa  Context-local state for delegate_task child execution.

A Hermes process may itself be a Kanban dispatcher worker with HERMES_KANBAN_* in
os.environ. In-process delegate_task children and cron jobs fired via
``cronjob(action="run")`` are NOT dispatcher-owned, so identity gates must fail
closed for them without mutating the process-global environment.
é    )ÚannotationsN)Úcontextmanager)Ú
ContextVarÚToken)ÚIteratorÚMappingÚMutableMappingÚoverloadÚhermes_delegated_child_contextF)ÚdefaultzContextVar[bool]Ú_DELEGATED_CHILD_CONTEXTÚ#hermes_non_dispatcher_owned_contextÚ_NON_DISPATCHER_OWNED_CONTEXTÚHERMES_DELEGATED_CHILD_CONTEXT)ÚHERMES_KANBAN_TASKÚHERMES_KANBAN_RUN_IDÚHERMES_KANBAN_CLAIM_LOCKÚHERMES_KANBAN_GOAL_MODEÚHERMES_KANBAN_GOAL_MAX_TURNSztuple[str, ...]ÚKANBAN_ENV_KEYSc              #  óä   K  — t         j                  d«      }	 ddlm}  || «      5  d–— ddd«       t         j	                  |«       y# 1 sw Y   ŒxY w# t         j	                  |«       w xY w­w)zÒMark child execution and isolate its task-local session identity. Even a context
    entered without an id must restore the parent's session ContextVar (child
    construction calls ``set_current_session_id``).Tr   )Úscoped_current_session_idN)r   ÚsetÚgateway.session_contextr   Úreset)Ú
session_idÚtokenr   s      ú=/home/ubuntu/.hermes/hermes-agent/agent/delegation_context.pyÚdelegated_child_contextr      s`   è ø€ ô
 %×(Ñ(¨Ó.€Eð.ÝEá& zÓ2ñ 	Û÷	ô 	!×&Ñ& uÕ-÷	ð 	ûô 	!×&Ñ& uÕ-üs1   ‚A0™A §A
¬A ´A0Á
AÁA ÁA-Á-A0c                 ó<   — t        t        j                  «       «      S )z<Return True while code is running for a delegate_task child.)Úboolr   Úget© ó    r   Úis_delegated_child_contextr%   +   s   € äÔ(×,Ñ,Ó.Ó/Ð/r$   c                 ó,   — t         j                  d«      S )zOToken form of :func:`non_dispatcher_owned_context` for long try/finally scopes.T)r   r   r#   r$   r   Ú"enter_non_dispatcher_owned_contextr'   0   s   € ä(×,Ñ,¨TÓ2Ð2r$   c                ó.   — t         j                  | «       y)zERestore the flag saved by :func:`enter_non_dispatcher_owned_context`.N)r   r   ©r   s    r   Ú!exit_non_dispatcher_owned_contextr*   5   s   € ä!×'Ñ'¨Õ.r$   c               #  ó`   K  — t        «       } 	 d–— t        | «       y# t        | «       w xY w­w)aY  Mark in-process execution that does NOT own the dispatcher's Kanban task; without it
    a cron agent run inside a worker is misread as that worker (kanban toolset force-added,
    ``kanban_complete`` defaulting to its task). ContextVar-scoped rather than clearing
    os.environ, which the worker's claim heartbeat and concurrent readers share.N)r'   r*   r)   s    r   Únon_dispatcher_owned_contextr,   :   s)   è ø€ ô /Ó0€Eð1Ûä)¨%Õ0øÔ)¨%Õ0üs   ‚.Ž ’.ž+«.c                 óD   — t        «       xs t        j                  «        S )zHThe single predicate every ``HERMES_KANBAN_*`` identity gate should use.)Ú"is_delegated_child_process_contextr   r"   r#   r$   r   Ú"is_dispatcher_owned_worker_contextr/   G   s   € ä2Ó4Ò[Ô8U×8YÑ8YÓ8[Ð\Ð\r$   c                 óz   — t        «       syt        j                  j                  d«      xs dj	                  «       S )u�  The board task this execution OWNS: ``HERMES_KANBAN_TASK`` for the dispatcher-owned
    worker, ``""`` otherwise. Tool access is not worker identity â€” a profile can expose the
    kanban toolset interactively, and children/cron runs inherit the env var â€” so every
    reader that turns the task id into worker behaviour (guidance, stop nudge, terminal
    outcomes) goes through this one helper.Ú r   )r/   ÚosÚenvironr"   Ústripr#   r$   r   Úowned_kanban_taskr5   L   s/   € ô .Ô/ØÜ�J‰J�N‰NÐ/Ó0Ò6°B×=Ñ=Ó?Ð?r$   c                 ó˜   — t        t        j                  «       «      xs, t        t        j                  j                  t
        «      «      S )z?Return True in this process or a subprocess spawned by a child.)r!   r   r"   r2   r3   ÚDELEGATED_CHILD_ENV_MARKERr#   r$   r   r.   r.   W   s/   € äÔ(×,Ñ,Ó.Ó/Òc´4¼¿
¹
¿¹ÔGaÓ8bÓ3cÐcr$   c                 óN   — 	 ddl m}  t         | «       «      S # t        $ r Y yw xY w)z·The board root this process's Kanban lineage lives under (``kanban_home()``); ``"1"`` when it
    cannot be resolved, which readers treat as "fence every board" (the pre-path marker).r   ©Úkanban_homeÚ1)Úhermes_cli.kanban_dbr:   ÚstrÚ	Exceptionr9   s    r   Ú_fenced_kanban_rootr?   \   s)   € ðÝ4Ü‘;“=Ó!Ð!øÜò Ùðús   ‚ ˜	$£$c                óâ   — | j                  «       D ��ci c]  \  }}|t        vsŒ||“Œ }}}t        | j                  t        «      xs d«      }|r|dk7  r|n	t        «       |t        <   |S c c}}w )aØ  Remove worker identity, retaining board/location and an inherited write fence.

    TASK absence alone would promote a descendant to an orchestrator. The marker
    survives later execs, including scripts that remove TASK themselves. This is
    cooperative runtime scoping, not confinement of code with direct SQLite access.

    The marker's value is the fenced board ROOT, so the fence applies to the lineage's
    board and not to every Kanban DB the descendant touches: a child running a repro
    against a temp ``HERMES_HOME`` got a silently read-only board there. An inherited
    path-valued marker is kept (a grandchild that moved HERMES_HOME must not re-fence
    onto its scratch root and unfence the real one).
    r1   r;   )Úitemsr   r=   r"   r7   r?   )ÚenvÚkÚvÚcleanedÚ	inheriteds        r   Úscrub_kanban_envrG   f   sk   € ð !$§	¡	£×H™˜˜1¨q¼Ò/Gˆq�!‰tÐH€GÑHÜ�C—G‘GÔ6Ó7Ò=¸2Ó>€IÙ7@ÀYÐRUÒEU©)Ô[nÓ[p€GÔ&Ñ'Ø€Nùó Is
   ”A+¥A+c                ó  — t         j                  «       ryt        j                  j                  t        d«      }|sy|dk(  ryddlm}  || «      j                  «       j                  «       }t        j                  j                  dd«      j                  «       }|r(| ||«      j                  «       j                  «       k(  ry	 |j                   ||«      j                  «       j                  «       «       y# t        $ r Y yw xY w)af  Whether Kanban mutations at *path* (a board DB or board-metadata root) are denied for this
    process: always for an in-process delegate child (the parent's own board); for a spawned
    descendant only when *path* is the dispatcher-pinned ``HERMES_KANBAN_DB`` or lies under the
    fenced root the marker carries. A legacy ``"1"`` marker fences everything.Tr1   Fr;   r   )ÚPathÚHERMES_KANBAN_DB)r   r"   r2   r3   r7   ÚpathlibrI   Ú
expanduserÚresolver4   Úrelative_toÚ
ValueError)ÚpathÚmarkerrI   ÚtargetÚpinneds        r   Úkanban_path_is_fencedrT   y   sÙ   € ô
  ×#Ñ#Ô%ØÜ�Z‰Z�^‰^Ô6¸Ó;€FÙØØ�‚}ØÝÙ�$‹Z×"Ñ"Ó$×,Ñ,Ó.€FÜ�Z‰Z�^‰^Ð.°Ó3×9Ñ9Ó;€FÙ�&™D ›L×3Ñ3Ó5×=Ñ=Ó?Ò?ØðØ×Ñ™4 ›<×2Ñ2Ó4×<Ñ<Ó>Ô?ð øô ò Ùðús   Ã3C: Ã:	DÄDc                 ó   — y ©Nr#   ©rB   s    r   Údelegated_child_subprocess_envrX   ‘   s   € ØNQr$   c                 ó   — y rV   r#   rW   s    r   rX   rX   •   s   € ØORr$   c                ó  — t        «       sVt        j                  j                  d«      s7| r&| j                  d«      s$| j                  t        «      s| €dS t        | «      S t        | €t        j                  «      S | «      S )zùCarry worker/delegate descendant denial across a real process spawn.

    Location and credentials are untouched; callers retain their existing secret policy.
    Dispatcher workers and supervised tool transports grant their own explicit scope.
    r   N)r.   r2   r3   r"   r7   ÚdictrG   rW   s    r   rX   rX   ™   sc   € ô /Ô0´B·J±J·N±NÐCWÔ4XÙ˜Ÿ™Ð!5Ô6¸#¿'¹'ÔB\Ô:]Ø�{ˆtÐ1¬¨S«	Ð1Ü¨#¨+œBŸJ™JÓ?Ð?¸3Ó?Ð?r$   rV   )r   z
str | NoneÚreturnúIterator[None])r\   r!   )r\   úToken[bool])r   r^   r\   ÚNone)r\   r]   )r\   r=   )rB   z,Mapping[str, str] | MutableMapping[str, str]r\   údict[str, str])rP   z'os.PathLike[str] | str'r\   r!   )rB   zMapping[str, str]r\   r`   )rB   r_   r\   údict[str, str] | None)rB   z3Mapping[str, str] | MutableMapping[str, str] | Noner\   ra   )Ú__doc__Ú
__future__r   r2   Ú
contextlibr   Úcontextvarsr   r   Útypingr   r   r	   r
   r   Ú__annotations__r   r7   r   r   r%   r'   r*   r,   r/   r5   r.   r?   rG   rT   rX   r#   r$   r   ú<module>rh      sõ   ðòõ #ã 	Ý %ß )ß >Ó >á-7Ð8XÐbgÔ-hÐ Ð*Ó hñ 3=Ð=bÐlqÔ2rÐ Ð/Ó rà=Ð ð$€�ó ð ó.ó ð.ó0ó
3ó
/ð
 ò	1ó ð	1ó]ó
@ódó
óó&ð0 
Ú Qó 
Ø Qð 
Û Ró 
Ø Rð @Dð@Ø	<ð@àô@r$   