+
    jHàjm‰  ã                  ó¼  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ^ RIHt ^ RIt^ RIHt ]'       d   ^ RIHt R_tR R	 ltR
tR] R2tRtR R ltR R ltR] 2tR R ltR] 2tR] 2tRR/R R lltR R ltR R lt R R  lt!R! R" lt"R# R$ lt#R% R& lt$R' R( lt%R) R* lt&R+ R, lt'R- R. lt(R`R/ R0 llt)R1 R2 lt*R3 R4 lt+R5t,R6t-R7 R8 lt.R9 R: lt/R; R< lt0R= R> lt1R? R@ lt2RA RB lt3RC RD lt4RE RF lt5RG RH lt6RI RJ lt7RK RL lt8RM RN lt9RO RP lt:RQ RR lt;RSR/RT RU llt<RSR/RV RW llt=RX RY lt>RZ R[ lt?R\ R] lt@^ R^IAHBtC R# )aay  Task workspace lifecycle: scratch/dir/worktree resolution (incl. git worktree creation), post-completion cleanup with containment guards, worker tmux teardown and the first-use scratch-workspace tip.

Split out of ``hermes_cli.kanban_db``; origin-resident helpers are reached
late-bound via ``_kb`` (import-cycle breaking) so monkeypatching
``kanban_db.<name>`` keeps working.
)ÚannotationsN)ÚPath)ÚOptional)ÚTYPE_CHECKING)Úrelease_lsp_clients)ÚTaskc               ó    € V ^8„  d   QhRRRR/# )é   ÚpathzPath | str | NoneÚreturnÚstr© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/hermes_cli/kanban_db_workspace.pyÚ__annotate__r      s   € ÷ 
Oñ 
OÐ%ð 
O¨#ñ 
Oó    c                óN   € V e!   \         P                  ! R\        V 4      4      # R# )uÞ  Unicode-form-insensitive identity for a filesystem path.

macOS hands back DECOMPOSED path strings (NFD: ``o`` + U+0308) for names the
user typed in composed form (NFC: ``Ã¶``) â€” a OneDrive/FileProvider path like
``OneDrive-PersÃ¶nlich`` round-trips through ``git rev-parse --show-toplevel``
as NFD while the DB row holds NFC. Raw ``Path`` equality then reports a real
repo root as "not a repo" purely on Unicode form, so every path identity
check here goes through this key.
ÚNFCÚ )ÚunicodedataÚ	normalizer   ©r
   s   &r   Ú	_path_keyr      s%   € ð 7;Ò6FŒ;× Ò  ¬¨D«	Ó2ÐNÈBÐNr   z+('done', 'archived', 'failed', 'cancelled')zgSELECT 1 FROM task_links l JOIN tasks t ON t.id = l.child_id WHERE l.parent_id = ? AND t.status NOT IN z LIMIT 1zJSELECT workspace_kind, workspace_path, branch_name FROM tasks WHERE id = ?c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r	   Ú	repo_rootr   Úargsr   ÚtimeoutÚintr   zsubprocess.CompletedProcessr   )r   s   "r   r   r   7   s)   € ÷ ñ �Dð  ð ¨sð Ð7Rñ r   c               óî   € ^ RI HpHp V! V 4      pVf(   \        P                  ! RR\        V 4      .VO^RV4      # \        P                  ! RR\        V 4      .VORRRRVR\        P                  VR	7	      # )
zñ``git -C repo_root args``; never raises on a non-zero exit.

:func:`noninteractive_repo_git_env` (GHSA-7x36-8jrh-v4pw): the dispatcher runs ``worktree add``
unattended, which executes the repo's hooks, ``core.fsmonitor`` and smudge filters.
)ÚFILTER_DISCOVERY_FAILEDÚnoninteractive_repo_git_envÚgitz-Cr   Túutf-8ÚreplaceF)Úcapture_outputÚtextÚencodingÚerrorsr   ÚcheckÚstdinÚenv)Úhermes_cli._subprocess_compatr   r    Ú
subprocessÚCompletedProcessr   ÚrunÚDEVNULL)r   r   r   r   r    r*   s   &$*   r   Ú_gitr0   7   s�   € ÷ cÙ
% iÓ
0€CØ
‚{Ü×*Ò*¨E°4¼¸Y»Ð+OÈ$Ð+OÐQRÐTVÐXoÓpÐpÜ�>Š>Ø	�”c˜)“nÐ, tÐ,ØØ˜G¨IØØÜ× Ñ Øôð r   c               ó$   € V ^8„  d   QhRRRRRR/# ©r	   Úconnúsqlite3.ConnectionÚtask_idr   r   Úboolr   )r   s   "r   r   r   L   s'   € ÷ Qñ QÐ1ð Q¸Cð QÀDñ Qr   c                óP   € V P                  \        V34      P                  4       R J# ©N)ÚexecuteÚ_ACTIVE_CHILDREN_SQLÚfetchone©r3   r5   s   &&r   Ú_has_active_childrenr=   L   s$   € Ø�<‰<Ô,¨w¨jÓ9×BÑBÓDÈDÐPÐPr   z/SELECT 1 FROM tasks WHERE id = ? AND status IN c               ó$   € V ^8„  d   QhRRRRRR/# r2   r   )r   s   "r   r   r   U   s'   € ÷ Oñ OÐ.ð O¸ð OÀñ Or   c                óP   € V P                  \        V34      P                  4       R J# r8   )r9   Ú_TERMINAL_TASK_SQLr;   r<   s   &&r   Ú_is_terminal_taskrA   U   s$   € Ø�<‰<Ô*¨W¨JÓ7×@Ñ@ÓBÈ$ÐNÐNr   z`SELECT workspace_path FROM tasks WHERE id != ? AND workspace_path IS NOT NULL AND status NOT IN zTSELECT workspace_path FROM tasks WHERE workspace_path IS NOT NULL AND status NOT IN Úexclude_task_idTc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r	   r3   r4   r5   r   ÚkeyrB   r6   r   r   )r   s   "r   r   r   g   s4   € ÷ ñ Ø
ðØ'*ðØ14ðØJNðà	ñr   c               ó|  € V'       d'   V P                  \        V34      P                  4       pM#V P                  \        4      P                  4       pV FR  pVR ,          pV'       g   K   \	        \        V4      P                  4       P                  RR7      4      pYr8X  g   KQ   R# 	  R#   \         d     Kf  i ; i)Úworkspace_pathF©ÚstrictT)	r9   Ú_OTHER_LIVE_PATHS_SQLÚfetchallÚ_ANY_LIVE_PATHS_SQLr   r   Ú
expanduserÚresolveÚOSError)r3   r5   rD   rB   ÚrowsÚrowÚotherÚ	other_keys   &&&$    r   Ú_conn_uses_pathrS   g   s¤   € ÷ Ø�|‰|Ô1°G°:Ó>×GÑGÓI‰à�|‰|Ô/Ó0×9Ñ9Ó;ˆÛˆØÐ$Õ%ˆßÙð	Ü!¤$ u£+×"8Ñ"8Ó":×"BÑ"BÈ%Ð"BÓ"PÓQˆIð ÖÚñ ñ øô	 ô 	Úð	ús   Á+2B,Â,B;Â:B;c               ó    € V ^8„  d   QhRRRR/# )r	   r3   r4   r   z
list[Path]r   )r   s   "r   r   r   {   s   € ÷ ñ Ð"4ð ¸ñ r   c                ól  € ^ RI Hp V! V 4      pV'       d   \        V4      P                  4       MRp\        P
                  ! 4       R,          .p\        P                  ! 4       pVP                  4       '       dH   VP                  4        F3  pVP                  4       '       g   K  VP                  VR,          4       K5  	  . p\        4       pV Fa  p	V	P                  4       '       g   K  V	P                  4       p
Ve	   W£8X  d   K7  W¨9   d   K?  VP                  V
4       VP                  V
4       Kc  	  V# )aB  Every other board's ``kanban.db``. Raises ``OSError`` when the set is unknown.

``kanban_db_path`` follows ``HERMES_KANBAN_DB`` and would collapse every
slug onto the pinned file, so the scan uses the on-disk layout: the
default board at ``<home>/kanban.db`` and named boards at
``<home>/kanban/boards/<slug>/kanban.db``.
)Ú_main_db_fileNz	kanban.db)Úhermes_cli.kanban_db_connectrV   r   rM   Ú_kbÚkanban_homeÚboards_rootÚis_dirÚiterdirÚappendÚsetÚis_fileÚadd)r3   rV   Úcurrent_fileÚcurrentÚ
candidatesÚrootÚchildÚfoundÚseenr
   Úresolveds   &          r   Ú_sibling_board_db_filesri   {   sè   € õ ;á  Ó&€Lß.:Œd�<Ó ×(Ñ(Ô*À€GÜ—/’/Ó# kÕ1Ð2€JÜ�?Š?Ó€DØ‡{�{‡}‚}Ø—\‘\–^ˆEØ�|‰|�~Œ~Ø×!Ñ! %¨+Õ"5Ö6ñ $ð €EÜ“e€DÛˆØ�|‰|�~Š~ÙØ—<‘<“>ˆØÒ 8Ô#6ÙØÔÙØ�‰�ÔØ�‰�XÖñ ð €Lr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   Údb_filer   r5   r   rD   r   r6   r   )r   s   "r   r   r   œ   s(   € ÷ ñ  Dð °3ð ¸Sð ÀTñ r   c                óô   € V P                  4       R ,           p\        P                  ! VRRR7      p \        P                  Vn        \        WAVRR7      VP                  4        #   TP                  4        i ; i)z?mode=roTg      ð?)Úurir   F)rB   )Úas_uriÚsqlite3ÚconnectÚRowÚrow_factoryrS   Úclose)rk   r5   rD   rm   rQ   s   &&&  r   Ú_other_board_uses_pathrt   œ   sU   € Ø
�.‰.Ó
˜ZÕ
'€CÜ�OŠO˜C T°3Ô7€EðÜ#ŸK™KˆÔÜ˜u¨sÀEÔJà�‰�øˆ�‰�ús   ²"A% Á%A7c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r	   r3   r4   r5   r   r
   ú
Path | strr   úOptional[str]r   )r   s   "r   r   r   ¦   s,   € ÷ )ñ )Ø
ð)Ø'*ð)Ø2<ð)àñ)r   c                ó  €  \        \        V4      P                  4       P                  RR7      4      pT'       g   R#  \        YT4      '       d   R#   \        T 4      pT F  p \        YaT4      '       d    R# K  	  R#   \         d-   p\
        P                  P                  RY!T4        Rp?R# Rp?ii ; i  \        P                   d,   p\
        P                  P                  RY4        Rp?R# Rp?ii ; i  \         d,   p\
        P                  P                  RY4        Rp?R# Rp?ii ; i  \        \        P                  3 d.   p\
        P                  P                  R	YaT4        Rp? R# Rp?ii ; i)
a&  Why *path* must be kept: ``"shared"``, ``"unknown"``, or None when free.

``gc``, completion and deferred parent cleanup used to ``rmtree`` a shared
``workspace_path`` as soon as one of its tasks went terminal. Compare the
resolved path: a row may store ``~`` or a symlinked spelling.

The connection covers one board. A ready task on a named board can point
at the same directory. If that set of databases cannot be read, refuse
the delete (``"unknown"``) and log the board DB that failed, so one broken
sibling DB is not reported as a live sharer.
FrG   z+Cannot resolve workspace %s for task %s: %sNÚunknownÚsharedz+Cannot read live workspaces for task %s: %sz)Cannot list kanban boards for task %s: %sz'Cannot read board db %s for task %s: %s)r   r   rL   rM   rN   rX   Ú_logÚwarningrS   ro   ÚErrorri   rt   )r3   r5   r
   rD   ÚexcÚsiblingsrk   s   &&&    r   Ú_workspace_in_use_by_otherr€   ¦   sC  € ðÜœ˜T›
×-Ñ-Ó/×7Ñ7¸uÐ7ÓEÓFˆ÷ ÙðÜ˜4¨#×.Ò.Ùð /ð
Ü*¨4Ó0ˆó ˆð	Ü% g¸×<Ò<Úñ =ñ ñ øô3 ô Ü�‰×ÑÐFÈÐWZÔ[Ýûðûô �=‰=ô Ü�‰×ÑÐFÈÔUÝûðûô
 ô Ü�‰×ÑÐDÀgÔSÝûðûô œŸ™Ð'ô 	Ü�H‰H×ÑØ9¸7ÈSôö ûð		ús^   ‚2B ¿B; ÁC> Á&D7ÂB8Â!B3Â3B8Â;C;Ã C6Ã6C;Ã>D4Ä	 D/Ä/D4Ä7E?Å!E:Å:E?c               ó(   € V ^8„  d   QhRRRRRRRR/# ©	r	   r3   r4   r5   r   r
   rv   r   r6   r   )r   s   "r   r   r   Ò   s,   € ÷ ñ Ø
ðØ'*ðØ2<ðà	ñr   c           	     ó>  € \        WV4      pVf   R# VR8X  d"   \        P                  P                  RW4       M \        P                  P                  RW4        \        P                  ! WRR\        V4      RV/4       R#   \        P                   d     R# i ; i)	zJSkip removal and record why, when *path* may still be used by a live task.Frz   zVDeferring workspace cleanup for task %s: %s is still used by another non-terminal taskzWDeferring workspace cleanup for task %s: cannot tell whether another task still uses %sÚ!workspace_cleanup_deferred_sharedr
   ÚreasonT)r€   rX   r{   r|   Ú_append_eventr   ro   r}   )r3   r5   r
   r…   s   &&& r   Ú_defer_shared_workspace_cleanupr‡   Ò   sŸ   € ô (¨°tÓ<€FØ‚~ÙØ�ÔÜ�‰×Ñð(àõ	
ô 	�‰×Ñð)àô	
ð
Ü×ÒØÐ>Ø”S˜“Y ¨&Ð1ô	
ñ øô �=‰=ô ØÙðús   Á%B ÂBÂBc               ó(   € V ^8„  d   QhRRRRRRRR/# r‚   r   )r   s   "r   r   r   ï   s,   € ÷ ñ Ø
ðØ'*ðØ2<ðà	ñr   c                ó¢   € \        V4      P                  4       pVP                  4       ;'       d     \        V4      ;'       d    \	        WV4      # )z™Defer removing a linked worktree another live task may still use.

Only a real linked worktree is ever removed, so the sharing scan runs just
for those.
)r   rL   r[   Ú_is_linked_worktree_checkoutr‡   )r3   r5   r
   Úwts   &&& r   Ú_defer_shared_worktree_cleanuprŒ   ï   sN   € ô 
ˆd‹×	Ñ	Ó	 €Bà
�	‰	‹÷ 	Að 	AÜ(¨Ó,÷	Að 	Aä+¨D¸4Ó@ðr   c               ó    € V ^8„  d   QhRRRR/# )r	   r
   rv   r   r   r   )r   s   "r   r   r   ÿ   s   € ÷ 2ñ 2˜
ð 2 tñ 2r   c                ód   € \        \        \        P                  P	                  V 4      4      4      # )zJAbsolute, ``..``-collapsed, NFC form of *path* WITHOUT following symlinks.)r   r   Úosr
   Úabspathr   s   &r   Ú_lexical_pathr‘   ÿ   s   € ä”	œ"Ÿ'™'Ÿ/™/¨$Ó/Ó0Ó1Ð1r   c               ó    € V ^8„  d   QhRRRR/# )r	   Úpr   r   ztuple[bool, Optional[str]]r   )r   s   "r   r   r     s   € ÷ Hñ H $ð HÐ+Eñ Hr   c                ó²  aa€  V P                  RR7      p\        T 4      o. oR T3R llp\        P                  P                  RR4      P                  4       pT'       dw   \        T4      P                  4       p\        P                  ! \        4      ;_uu_ 4        TP                  pT! TTP                  RR7      TP                  3R4       RRR4        \        P                  ! 4       pTP                  RR7      pTeê   T! TXR\        P                  4       . p\        P                  ! \        4      ;_uu_ 4        \!        TR,          R
,          P                  RR7      P#                  4       4      pRRR4       T Ff  p	\        P                  ! \        4      ;_uu_ 4        T	P%                  4       '       d#   T! YgRR
T	P                  R	3T	P                  4       RRR4       Kh  	  S Fn  w  r«pY8X  d   K   TP'                  T
4      '       dI   \(        ;QJ d    T3R lT 4       F  '       g   K   RM	  RM! T3R lT 4       4      '       d   RT3u # Kn  Kp  	  R#   \         d    Ru # i ; i  + '       g   i     EL¯; i  \         d    Rp ELši ; i  + '       g   i     EL.; i  + '       g   i     EKA  ; i  \*         d     Kæ  i ; i)aT  Return whether *p* is managed scratch storage and the matching board.

*p* must be strictly below a managed root both after resolving symlinks
AND lexically (as spelled, without resolving). Resolved containment alone
is not enough: when a root is itself a symlink to a broad directory
(relocated storage, or a planted link), every path inside the link target
would resolve "under" the root, so a scratch task naming such a path
directly would get it rmtree'd. Tasks created through the root are spelled
through it, so the lexical check keeps them managed. A root's lexical form
is accepted both as configured and with its anchor (kanban home, or the
override's parent) resolved, so a process spelling a symlinked home by its
real path still matches; the managed ``kanban/.../workspaces`` components
themselves are never resolved for the lexical check.
FrG   Nc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r	   Úanchorr   Úanchor_realÚpartsztuple[str, ...]Úboardrw   r   ÚNoner   )r   s   "r   r   Ú0_managed_scratch_path_info.<locals>.__annotate__  s4   € ÷ 	ñ 	Øð	Ø#'ð	Ø0?ð	ØHUð	à	ñ	r   c                ó2  <€ V P                   ! V!  p\        P                  ! \        4      ;_uu_ 4        SP	                  VP                  R R7      \        V4      \        VP                   ! V!  4      3V34       RRR4       R#   + '       g   i     R# ; i©FrG   N)ÚjoinpathÚ
contextlibÚsuppressrN   r]   rM   r‘   )r–   r—   r˜   r™   rd   Úrootss   &&&& €r   Ú	_add_rootÚ-_managed_scratch_path_info.<locals>._add_root  sr   ø€ ð �Š Ñ&ˆÜ× Ò ¤×)Õ)Ø�L‰LØ—‘ E�Ó*Ü˜tÓ$¤m°K×4HÒ4HÈ%Ñ4PÓ&QÐRØðô ÷ *×)×)Ò)ús   ´ABÂB	ÚHERMES_KANBAN_WORKSPACES_ROOTr   ÚkanbanÚ
workspacesÚboardsc              3  ó`   <"  € T F#  pSV8g  ;'       d    SP                  V4      x € K%  	  R # 5ir8   )Úis_relative_to)Ú.0ÚlexÚp_lexs   & €r   Ú	<genexpr>Ú-_managed_scratch_path_info.<locals>.<genexpr>F  s.   øé € ð 2ÙFS¸s�˜‘×:Ð: ×!5Ñ!5°cÓ!:Ô:Ãmùs   ƒ.”.T)FN)r¥   r¦   )rM   rN   r‘   r�   ÚenvironÚgetÚstripr   rL   rŸ   r    ÚparentÚnamerX   rY   ÚDEFAULT_BOARDÚlistr\   r[   r©   ÚanyÚ
ValueError)r“   Úp_absr¢   ÚoverrideÚoverride_rootÚoverride_parentÚhomeÚ	home_realÚentriesÚentryrd   Úlexical_rootsr™   r¬   r¡   s   &            @@r   Ú_managed_scratch_path_inforÁ     se  ù€ ðØ—	‘	 �	Ó'ˆô ˜!Ó€Eà@B€E÷	ð 	ô �z‰z�~‰~Ð=¸rÓB×HÑHÓJ€HßÜ˜X›×1Ñ1Ó3ˆÜ× Ò ¤×)Õ)Ø+×2Ñ2ˆOÙØØ×'Ñ'¨uÐ'Ó5Ø×#Ñ#Ð%Øô	÷ *ðÜ�ŠÓ ˆà—L‘L¨�LÓ.ˆ	ð ÒÙ�$˜	Ð#;¼S×=NÑ=NÔOØ ˆÜ× Ò ¤×)Õ)Ü˜D 8�O¨hÕ6×?Ñ?ÀuÐ?ÓM×UÑUÓWÓXˆG÷ *ãˆEÜ×$Ò$¤W×-Õ-Ø—<‘<—>’>ÙØ¨(°H¸e¿j¹jÈ,Ð)WÐY^×YcÑYcô÷ .Ñ-ñ ó ',Ñ"ˆ˜UØŒ=Ùð	Ø×#Ñ# D×)Ò)¯c«cô 2ÙFSó2¯c¯cªcô 2ÙFSó2÷ /ò /ð ˜U�{Ò"ñ/Ñ)ñ	 ',ð Ðøôo ô ØÒðú÷( *×)Ð)ûô ô Ø‹ðú÷
 *×)Ð)ú÷ .×-Ñ-ûô ô 	Úð	úsq   „I# Â3I6Ã'J
 Å8JÆ(9J2Ç>KÈ
KÈ KÈ7KÉKÉ#I3É2I3É6J	Ê
JÊJÊJ/	Ê2KËKËKc               ó$   € V ^8„  d   QhRRRRRR/# )r	   r3   r4   r5   r   r   úOptional[Path]r   )r   s   "r   r   r   O  s"   € ÷ 4ñ 4Ð/ð 4¸#ð 4À.ñ 4r   c                óÒ   € V P                  RV34      P                  4       pV'       d   VR,          R8w  g   VR,          '       g   R# \        VR,          4      P                  4       # )zRExpanded ``workspace_path`` when the task uses a scratch workspace, else ``None``.z=SELECT workspace_kind, workspace_path FROM tasks WHERE id = ?Úworkspace_kindÚscratchrF   N)r9   r;   r   rL   )r3   r5   rP   s   && r   Ú_scratch_workspacerÇ   O  s^   € à
�,‰,ØGØ	ˆ
ó÷ �hƒjð ÷ �#Ð&Õ'¨9Ô4¸CÐ@P×<QÔ<QÙÜ�Ð$Õ%Ó&×1Ñ1Ó3Ð3r   c               ó    € V ^8„  d   QhRRRR/# )r	   r“   r   r   r6   r   )r   s   "r   r   r   Z  s   € ÷ ,ñ , ð ,¨ñ ,r   c                ó&   € \        V 4      ^ ,          # )ur  True iff *p* is a STRICT descendant of a kanban-managed ``workspaces/``
root (``HERMES_KANBAN_WORKSPACES_ROOT``, ``<kanban_home>/kanban/workspaces``,
or ``<kanban_home>/kanban/boards/<slug>/workspaces``). A path equal to a
root is not managed (deleting it would wipe every task's scratch dir);
``<kanban_home>/kanban``, ``.../logs`` and ``.../boards/<slug>`` hold
Hermes' own DB and metadata. :func:`_cleanup_workspace` refuses
``rmtree`` outside managed storage â€” a board ``default_workdir`` on a real
source tree paired with ``workspace_kind='scratch'`` would otherwise make
task completion delete user data.

See #28818.
)rÁ   )r“   s   &r   Ú_is_managed_scratch_pathrÊ   Z  s   € ô & aÓ(¨Õ+Ð+r   c               ó$   € V ^8„  d   QhRRRRRR/# ©r	   r3   r4   r5   r   r   rš   r   )r   s   "r   r   r   j  s"   € ÷ =ñ =Ð/ð =¸#ð =À$ñ =r   c                ól  €  V P                  \        V34      P                  4       pV'       g   R# VR,          pVR,          pV\        9  g	   V'       g   \	        W4       R# \        W4      '       d$   \        P                  P                  RW1V4       R# VR8X  d>   \        W4       \        WV4      '       g   \        WVR,          4       \	        W4       R# \        V4      pVP                  4       '       d‘   \        V4      '       d`   \        WV4      '       gM   \!        \#        V4      4       \$        P&                  ! VRR7       \        P                  P                  R	V4       M \        P                  P)                  R
W4       \        W4       \	        W4       R#   \*         d     R# i ; i)aa  Remove a task's scratch workspace dir and kill its stale tmux session.
Called from :func:`complete_task` after the transaction commits; best-effort
so cleanup never blocks completion. ``scratch`` is removed; ``worktree``
only when provably free of work (clean tree, every commit reachable from a
remote-tracking ref); ``dir`` is intentionally preserved.NrÅ   rF   zVDeferring %s workspace cleanup for task %s: active children still need workspace at %sÚworktreeÚbranch_nameT©Úignore_errorszRemoved scratch workspace: %sz�Refusing to remove out-of-scratch workspace for task %s: %s (workspace_kind='scratch' but path is outside any kanban-managed workspaces root))r9   Ú_WORKSPACE_ROW_SQLr;   Ú_REMOVABLE_KINDSÚ_try_cleanup_parent_workspacesr=   rX   r{   ÚdebugÚ_cleanup_worker_tmuxrŒ   Ú_cleanup_worktree_workspacer   r[   rÊ   r‡   r   r   ÚshutilÚrmtreer|   Ú	Exception)r3   r5   rP   Úkindr
   Úwps   &&    r   Ú_cleanup_workspacerÝ   j  sZ  € ð7Ø�l‰lÔ-°¨zÓ:×CÑCÓEˆßÙØ!Ð"2Õ3ˆØ!Ð"2Õ3ˆØÔ'Ô'¯tô +¨4Ô9Ùô   ×.Ò.Ü�H‰H�N‰Nð=à˜tôñ
 ð �:ÔÜ  Ô/Ü1°$À×FÒFÜ+¨G¸3¸}Õ;MÔNÜ*¨4Ô9ÙÜ�$‹ZˆØ�9‰9�;Š;ô (¨×+Ò+Ü6°tÀd×KÒKÜ'¬¨B«Ô0Ü—M’M "°DÕ9Ü—H‘H—N‘NÐ#BÀBÔGøä—‘× Ñ ð6ð ô	ô 	˜TÔ+ô 	' tÖ5øÜô Úðús0   ‚,F$ ±$F$ ÁF$ Á#2F$ ÂAF$ ÃCF$ Æ$F3Æ2F3c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r5   r   r
   rÏ   rw   r   rš   r   )r   s   "r   r   r   ª  s2   € ÷ Fñ FØðFØðFØ*7ðFà	ñFr   c                óh  €  ^ RI HpHp  \	        T4      P                  4       pTP                  4       '       g   R# \        T4      pTe   TP                  R8w  d   R# TP                  p\        TP                  RR7      4      \        TP                  RR7      4      8X  d   R# T! \        T4      \        T4      4      '       g   T! \        T4      4      '       d#   \        P                  P                  RY4       R# TP                  RR7      p \        P                   ! 4       P                  RR7      p	T	e   Y˜8X  g   T	P%                  T4      '       d    \&        P(                  ! T4       \-        \        T4      4       \/        TR	R
\        T4      ^<R7      pTP0                  ^ 8w  d0   \2        P4                  ! R4       \/        TR	R
\        T4      ^<R7      pTP0                  ^ 8w  dZ   \        P                  P+                  RYTP6                  ;'       g    TP8                  ;'       g    RP;                  4       4       R# \        P                  P=                  RT4       T;'       g    RP;                  4       ;'       g    RT  2pTP?                  R4      '       d   \/        TRRT^R7       R# R#   \         d     R# i ; i  \"         d    Rp	 EL£i ; i  \"         d7   p
\        P                  P+                  RY	;'       g    RYz4        Rp
?
R# Rp
?
ii ; i  \         d     R# i ; i)a‰  Remove a finished task's linked git worktree when it holds no work.
Mirrors the CLI startup pruner (``cli._prune_stale_worktrees``): removal
requires a clean tree AND every commit reachable from a remote-tracking
ref; any doubt (dirty, unpushed, unresolvable repo, failing git) preserves
it. The auto-generated ``wt/<task-id>`` branch is deleted with it; custom
branches are kept. Best-effort.)Ú_worktree_has_unpushed_commitsÚ_worktree_is_dirtyNz.gitFrG   z=Preserving worktree for task %s: dirty or unpushed work at %sz;Preserving worktree for task %s: cannot leave %s for %s: %sz<deleted cwd>rÎ   Úremove©r   gš™™™™™¹?z0git worktree remove failed for task %s at %s: %sr   zRemoved worktree workspace: %súwt/Úbranchz-D) Úhermes_cli.worktree_opsrà   rá   rÚ   r   rL   r[   Ú_git_common_dirr³   r²   r   rM   r   rX   r{   ÚinfoÚcwdrN   r©   r�   Úchdirr|   r   r0   Ú
returncodeÚtimeÚsleepÚstderrÚstdoutr±   rÕ   Ú
startswith)r5   r
   rÏ   rà   rá   rÜ   Úcommonr   Úworktree_pathré   r~   Úresultrå   s   &&&          r   r×   r×   ª  s›  € ðß^ð9Ü�$‹Z×"Ñ"Ó$ˆØ�y‰y�{Š{ÙÜ  Ó$ˆØŠ>˜VŸ[™[¨FÔ2ÙØ—M‘Mˆ	Ü�R—Z‘Z u�ZÓ-Ó.´)¸I×<MÑ<MÐUZÐ<MÓ<[Ó2\Ô\ÙÙœc "›g¤s¨9£~×6Ò6Ñ:XÔY\Ð]_ÓY`×:aÒ:aÜ�H‰H�M‰MØOØôñ ð
 Ÿ
™
¨%˜
Ó0ˆð	Ü—(’(“*×$Ñ$¨EÐ$Ó2ˆCð Š;˜#Ô.°#×2DÑ2DÀ]×2SÒ2SðÜ—’˜Ô#ô 	œC Ó.Ô/Ü�i ¨X´s¸2³wÈÔKˆØ×Ñ Ô!ô �JŠJ�sŒOÜ˜) Z°¼3¸r»7ÈBÔOˆFØ×Ñ Ô!Ü�H‰H×ÑØBØ˜fŸm™m×BÐB¨v¯}©}×BÐBÀ×IÑIÓKôñ Ü�‰�‰Ð7¸Ô<Ø×#Ð# ×*Ñ*Ó,×?Ð?°#°g°Y°ˆØ×Ñ˜U×#Ò#Ü�˜H d¨F¸B×?ñ $øôq ô Úðûô2 ô 	ð ‹Cð		ûô ô Ü—‘× Ñ ØQØ×3Ð3 O°Yôõ ûðûô2 ô Úðús®   ‚J8 ‹/L" ¼ L" ÁAL" Â%AL" Ã?L" Ä%K
 Ä7 L" ÅK Å/B+L" ÈL" È/L" É(L" É/L" ÊL" Ê$L" Ê8KËKË
KËL" ËKËL" ËLË)+LÌL" ÌLÌL" Ì"L1Ì0L1c               ó$   € V ^8„  d   QhRRRRRR/# rÌ   r   )r   s   "r   r   r   ó  s"   € ÷ &ñ &Ð);ð &Àcð &Èdñ &r   c                ó  €  V P                  RV34      P                  4       pV EFO  w  pV P                  \        V34      P                  4       pV'       dD   VR,          \        9  g2   VR,          '       d#   \        W4      '       d   \        W4      '       d   Kx  VR,          pVR,          R8X  d*   \        WV4      '       d   K£  \        W5VR,          4       K¸  \        V4      pVP                  4       '       g   KÛ  \        V4      '       g   Kî  \        WV4      '       d   EK  \        \        V4      4       \        P                   ! VRR7       \"        P$                  P'                  RW64       EKR  	  R	#   \(         d     R	# i ; i)
z®Run the deferred cleanup of any parent scratch/worktree workspace whose
children are now all done/archived/failed/cancelled (called after each
child completes).

See #33774.
z3SELECT parent_id FROM task_links WHERE child_id = ?rÅ   rF   rÎ   rÏ   TrÐ   z9Deferred cleanup: removed parent %s scratch workspace: %sN)r9   rJ   rÒ   r;   rÓ   rA   r=   rŒ   r×   r   r[   rÊ   r‡   r   r   rØ   rÙ   rX   r{   rÕ   rÚ   )r3   r5   ÚparentsÚ	parent_idrP   Úws_pathrÜ   s   &&     r   rÔ   rÔ   ó  s9  € ðØ—,‘,ØAØˆJó
÷ ‰(‹*ð 	ô $‰LˆYØ—,‘,Ô1°I°<Ó@×IÑIÓKˆCçØÐ'Õ(Ô0@Ô@ØÐ+×,Ô,Ü(¨×9Ò9Ü'¨×8Ò8áØÐ*Õ+ˆGØÐ#Õ$¨
Ô2Ü1°$À7×KÒKÙÜ+¨IÀÀMÕ@RÔSÙÜ�g“ˆBØ—9‘9—;’;ÙÜ'¨×+Ô+Ü2°4ÀG×LÒLÚÜ#¤C¨£GÔ,Ü—’˜b°Õ5Ü—‘—‘ÐZÐ\e×jó1 $øô2 ô Úðús    ‚A6E; Á9BE; ÄA&E; Å;F
Æ	F
c               ó$   € V ^8„  d   QhRRRRRR/# rÌ   r   )r   s   "r   r   r     s"   € ÷ ñ Ð1ð ¸Cð ÀDñ r   c           
     ó¼  €  V P                  RV34      P                  4       pV'       d   VR,          '       g   R# RVR,           2p\        P                  ! RRRVRR	.R
R
RR^RR7      pVP                  P                  4       R8X  dA   \        P                  ! RRRV.R
^RR7       \        P                  P                  RV4       R# R#   \         d     R# i ; i)zAKill the tmux session associated with a task's assignee, if dead.z'SELECT assignee FROM tasks WHERE id = ?ÚassigneeNzswarm-Útmuxz
list-panesz-tz-Fz#{pane_dead}Tr"   r#   F)r$   r%   r&   r'   r   r(   Ú1zkill-session)r$   r   r(   zKilled stale tmux session: %s)
r9   r;   r,   r.   rï   r±   rX   r{   rÕ   rÚ   )r3   r5   rP   ÚsessionÚouts   &&   r   rÖ   rÖ     sÕ   € ðØ�l‰lØ5¸°zó
ç
‰(‹*ð 	÷ ˜#˜jŸ/œ/Ùà˜3˜z�?Ð+Ð,ˆÜ�nŠnØ�\ 4¨°$¸ÐGØ d°WÀYÐXYØô
ˆð
 �:‰:×ÑÓ Ô$Ü�NŠN˜F N°D¸'ÐBÐSWÐabÐjoÕpÜ�H‰H�N‰NÐ:¸GÖDñ %øô ô Úðús   ‚(C «C ¼BC ÃCÃCz.scratch_tip_shownu½   scratch workspaces are ephemeral â€” they're deleted when the task completes. Use --workspace worktree: (git worktree) or --workspace dir:/abs/path (existing dir) to preserve worker output.c               ó   € V ^8„  d   QhRR/# )r	   r   r   r   )r   s   "r   r   r   <  s   € ÷ :ñ : Dñ :r   c                 óB   € \         P                  ! 4       \        ,          # )z<Path to the per-install scratch-workspace-tip sentinel file.)rX   rY   Ú_SCRATCH_TIP_SENTINEL_NAMEr   r   r   Ú_scratch_tip_sentinel_pathr  <  s   € ä�?Š?ÓÔ9Õ9Ð9r   c               ó   € V ^8„  d   QhRR/# )r	   r   r6   r   )r   s   "r   r   r   A  s   € ÷ ñ ˜Dñ r   c                 óX   €  \        4       P                  4       #   \         d     R# i ; i)u–   True iff the scratch-workspace tip was already emitted on this install.
Best-effort â€” any error re-emits, the safer failure mode for a help message.F)r  ÚexistsrN   r   r   r   Ú_scratch_tip_shownr  A  s+   € ðÜ)Ó+×2Ñ2Ó4Ð4øÜô Úðús   ‚ š)¨)c               ó   € V ^8„  d   QhRR/# )r	   r   rš   r   )r   s   "r   r   r   J  s   € ÷ ñ  ñ r   c                 óž   €  \        4       p V P                  P                  RRR7       V P                  RR7       R#   \         d     R# i ; i)z˜Touch the sentinel so future scratch workspaces stay silent. Best-effort:
a failure means the tip may appear once more, preferable to crashing dispatch.T©rö   Úexist_ok)r  N)r  r²   ÚmkdirÚtouchrN   r   s    r   Ú_mark_scratch_tip_shownr  J  sF   € ðÜ)Ó+ˆØ�‰×Ñ $°ÐÔ6Ø�
‰
˜Dˆ
Ö!øÜô Úðús   ‚9= ½AÁAc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r	   r3   r4   r5   r   rÅ   rw   r   rš   r   )r   s   "r   r   r   U  s0   € ÷ "ñ "Ø
ð"àð"ð "ð"ð 
ñ	"r   c           	     óœ  € T;'       g    RR8w  g   \        4       '       d   R#  \        P                  P                  R\        V4       \        P
                  ! V 4      ;_uu_ 4        \        P                  ! WRR\        /4       RRR4       \        4        R#   + '       g   i     L; i  \         d     L,i ; i  \        4        i ; i)z¾Emit the first-use scratch-workspace tip once per install, right after a
scratch workspace is materialized. No-op for ``worktree``/``dir`` (preserved
by design) and once the sentinel exists.rÆ   Nzkanban: %s (task %s)Útip_scratch_workspaceÚmessage)	r  rX   r{   r|   Ú_SCRATCH_TIP_MESSAGEÚ	write_txnr†   rÚ   r  )r3   r5   rÅ   s   &&&r   Ú_maybe_emit_scratch_tipr  U  s›   € ð 	×#Ð#˜)¨	Ô1Ô5G×5IÒ5IÙð"Ü�‰×ÑÐ/Ô1EÀwÔOÜ�]Š]˜4× Õ Ü×ÒØÐ6ØÔ0Ð1ô÷ !ô 	 Ö!÷ !× ûô
 ô áðûô 	 Õ!úsH   ¥AB. Á(BÂB. ÂB+	Â&B. Â*B? Â+B. Â.B<Â9B? Â;B<Â<B? Â?Cc               ó    € V ^8„  d   QhRRRR/# ©r	   r
   r   r   rÃ   r   )r   s   "r   r   r   q  s   € ÷ &ñ &˜ð & ñ &r   c                óâ   € \         P                  ! V RR4      pVf   R#  \        V4      P                  4       P	                  4       #   \
         d    \        T4      P                  4       u # i ; i)zJReturn the git toplevel containing ``path``, or ``None`` if not in a repo.ú	rev-parsez--show-toplevelN)rX   Ú_git_outr   rL   rM   rÚ   )r
   rÿ   s   & r   Ú_git_toplevelr  q  s`   € ä
�,Š,�t˜[Ð*;Ó
<€CØ
‚{Ùð&Ü�C‹y×#Ñ#Ó%×-Ñ-Ó/Ð/øÜô &Ü�C‹y×#Ñ#Ó%Ò%ð&ús    &A Á$A.Á-A.c               ó$   € V ^8„  d   QhRRRRRR/# )r	   r   r   rÏ   r   r   r6   r   )r   s   "r   r   r   |  s!   € ÷ "ñ " $ð "°Sð "¸Tñ "r   c                ól   €  \        V R RRV 2^R7      pTP                  ^ 8H  #   \         d     R# i ; i)zshow-refz--verifyzrefs/heads/rã   F)r0   rÚ   rë   )r   rÏ   ró   s   && r   Ú_git_branch_existsr  |  sH   € ðÜ�i ¨Z¸;À{ÀmÐ9TÐ^`Ôaˆð ×Ñ Ñ!Ð!øô ô Úðús   ‚$ ¤3²3c               ó$   € V ^8„  d   QhRRRRRR/# )r	   r
   r   Úflagr   r   rÃ   r   )r   s   "r   r   r   „  s&   € ÷ Iñ I˜ð I Cð I¨Nñ Ir   c                óš   € \         P                  ! V R RV4      pV'       d*   \        V4      P                  4       P	                  RR7      # R# )r  ú--path-format=absoluteFrG   N)rX   r  r   rL   rM   )r
   r   rÿ   s   && r   Ú_git_abs_pathr#  „  s?   € Ü
�,Š,�t˜[Ð*BÀDÓ
I€Cß;>Œ4�‹9×ÑÓ!×)Ñ)°Ð)Ó7ÐHÀDÐHr   c               ó    € V ^8„  d   QhRRRR/# r  r   )r   s   "r   r   r   ‰  s   € ÷ 3ñ 3˜$ð 3 >ñ 3r   c                ó   € \        V R 4      # )ú--git-common-dir)r#  r   s   &r   rç   rç   ‰  s   € Ü˜Ð1Ó2Ð2r   c               ó    € V ^8„  d   QhRRRR/# )r	   r
   r   r   rw   r   )r   s   "r   r   r   �  s   € ÷ :ñ :˜dð : }ñ :r   c                ó2   € \         P                  ! V R R4      # )rå   z--show-current)rX   r  r   s   &r   Ú_git_current_branchr)  �  s   € Ü�<Š<˜˜hÐ(8Ó9Ð9r   c               ó    € V ^8„  d   QhRRRR/# )r	   r
   r   r   r6   r   )r   s   "r   r   r   ‘  s   € ÷ ñ  tð °ñ r   c                ó   € \         P                  ! V RRRR4      pV'       d   VP                  4       M. p\        V4      ^8H  ;'       dF    \	        V^ ,          4      P                  RR7      \	        V^,          4      P                  RR7      8g  # )z{True when *path* is a linked worktree (git-dir differs from common-dir).

One ``rev-parse`` call answers both directories.
r  r"  z	--git-dirr&  FrG   )rX   r  Ú
splitlinesÚlenr   rM   )r
   rÿ   Úliness   &  r   rŠ   rŠ   ‘  s   € ô
 �,Š,ØˆkÐ3°[ÐBTó€C÷ !$ˆC�N‰NÔ¨€EÜˆu‹:˜‰?÷ ð ÜˆU�1�X‹×Ñ eÐÓ,´°U¸1µX³×0FÑ0FÈeÐ0FÓ0TÑTðr   c               ó    € V ^8„  d   QhRRRR/# )r	   r
   r   r   r   )r   s   "r   r   r   Ÿ  s   € ÷ ñ  ð ¨$ñ r   c                ór   € T pVP                  4       '       g   WP                  8w  d   VP                  pK4  V# r8   )r  r²   )r
   rb   s   & r   Ú_nearest_existing_pathr1  Ÿ  s+   € Ø€GØ�n‰n×Ò 7¯n©nÔ#<Ø—.‘.ŠØ€Nr   c               ó    € V ^8„  d   QhRRRR/# r  r   )r   s   "r   r   r   ¦  s   € ÷ !ñ !¨ð !°.ñ !r   c                óœ   € \        V 4      P                  R R7      p \        V4      pVe   V# WP                  8X  d   R# VP                  pK2  r�   )r1  rM   r  r²   )r
   rb   r   s   &  r   Ú_repo_root_for_worktree_targetr4  ¦  sI   € Ü$ TÓ*×2Ñ2¸%Ð2Ó@€GØ
Ü! 'Ó*ˆ	ØÒ ØÐØ—n‘nÔ$ÙØ—.‘.Šr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r   r   ÚtargetrÏ   r   r   rš   r   )r   s   "r   r   r   ±  s(   € ÷ 
ñ 
 Dð 
°$ð 
ÀSð 
ÈTñ 
r   c                ó.  € VP                  4       p\        V 4      pVP                  4       '       d)   Ve%   \        \        V4      4      \        V4      8X  d   R# VP                  P                  RRR7       \        W4      '       d   RR\        V4      V.pMRRRV\        V4      R.p\        V .VO5R^</ pVP                  ^ 8w  dM   VP                  ;'       g    VP                  ;'       g    R	P                  4       p\        R
V RV RV 24      hR# )zDMaterialize ``target`` as a linked git worktree under ``repo_root``.NTr
  rÎ   r`   z-bÚHEADr   r   zgit worktree add failed for z on branch z: )rL   rç   r  r   r²   r  r  r   r0   rë   rî   rï   r±   ÚRuntimeError)r   r6  rÏ   Úrepo_commonr   ró   rî   s   &&&    r   Ú_ensure_git_worktreer;  ±  s   € à×ÑÓ €FÜ! )Ó,€KØ‡}�}‡‚˜;Ò2´yÄÐQWÓAXÓ7YÔ]fÐgrÓ]sÔ7sÙØ
‡M�M×Ñ ¨tÐÔ4Ü˜)×1Ò1Ø˜E¤3 v£;°Ð<‰à˜E 4¨´c¸&³kÀ6ÐJˆÜ�)Ð/˜dÒ/¨BÑ/€FØ×Ñ˜AÔØ—-‘-×6Ð6 6§=¡=×6Ð6°B×=Ñ=Ó?ˆÜØ*¨6¨(°+¸k¸]È"ÈVÈHÐUó
ð 	
ñ r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r   r   r5   r   rÏ   r   útuple[Path, str]r   )r   s   "r   r   r   Ä  s)   € ÷ ñ  $ð °ð À3ð ÐK[ñ r   c                ó@   € V R,          V,          p\        WV4       W23# )zCMaterialize the canonical ``<repo>/.worktrees/<task-id>`` worktree.ú
.worktrees)r;  )r   r5   rÏ   r6  s   &&& r   Ú_anchored_worktreer@  Ä  s$   € à˜Õ%¨Õ/€FÜ˜¨KÔ8ØÐÐr   r™   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   Útaskr   r™   rw   r   r=  r   )r   s   "r   r   r   Ë  s'   € ÷ E"ñ E" dð E"°mð E"ÐO_ñ E"r   c          	     ó8  € V P                   ;'       g    RP                  4       ;'       g    RV P                   2pV P                  '       Eg   V'       d   TM\        P
                  ! 4       p\        P                  ! V4      P                  R4      ;'       g    RP                  4       pV'       g   \        RV P                   RV: R24      h\        V4      P                  4       pVP                  4       '       g   \        RV: RV: R	24      h\        V4      pVf"   \        RV P                   R
V: RV: R24      h\        W`P                  V4      # \        V P                  4      P                  4       pVP                  4       '       g(   \        RV P                   RV P                  : R24      hVP                  RR7      pVP                  4       '       d¯   \!        V4      '       dž   \#        V4      p	W’8X  d   W‰3# \%        VP&                  4      p
V
ed   V
R,          V P                  ,          p\)        VP                  RR7      4      \)        V4      8w  d!   \+        W«V4       VP                  RR7      V3# Y‰;'       g    T3# \        V4      pVe0   \)        V4      \)        V4      8X  d   \        W`P                  V4      # \%        VP&                  4      pVf(   \        RV P                   RV P                  : R24      h\+        WgV4       Wr3# )aj  Resolve + materialize a linked git worktree for ``task``. With no
``task.workspace_path`` the anchor is the board's ``default_workdir`` so
every worktree lands under a board-owned repo (``<repo>/.worktrees/<id>``)
instead of the dispatcher's incidental CWD (whatever dir the gateway was
launched from); with no anchor configured we fail loudly rather than guess.r   rä   Údefault_workdirútask z> has workspace_kind=worktree but no workspace_path, and board zˆ has no default_workdir set. Set a board default workdir (a git repo) or create the task with --workspace worktree:<absolute-repo-path>.zboard z default_workdir z4 is not absolute; use an absolute path to a git repoz' has workspace_kind=worktree but board z is not inside a git repoz  has non-absolute worktree path z; use an absolute pathFrG   r?  z worktree path z? is not inside a git repo and does not point at a git repo root)rÏ   r±   ÚidrF   rX   Úget_current_boardÚread_board_metadatar°   r·   r   rL   Úis_absoluter  r@  rM   r  rŠ   r)  r4  r²   r   r;  )rB  r™   rÏ   Ú
board_slugÚboard_defaultr–   r   Ú	requestedÚrequested_resolvedÚactual_branchÚfallback_rootÚfallbacks   &$          r   Ú_resolve_worktree_workspacerQ  Ë  sþ  € ð ×#Ñ#×)Ð) r×0Ñ0Ó2×EÐE¸¸D¿G¹G¸9°o€KØ××Ñß#‘U¬×)>Ò)>Ó)@ˆ
Ü×0Ò0°Ó<×@Ñ@ÐARÓS×YÐYÐWY×`Ñ`ÓbˆßÜØ˜Ÿ™�yð !Ø'™Nð +=ð=óð ô �mÓ$×/Ñ/Ó1ˆØ×!Ñ!×#Ò#ÜØ˜™Ð&7¸Ñ7Hð I?ð ?óð ô " &Ó)ˆ	ØÒÜØ˜Ÿ™�yÐ GØ‘.Ð 1°-Ñ1BÐB[ð]óð ô " )¯W©W°kÓBÐBä�T×(Ñ(Ó)×4Ñ4Ó6€IØ× Ñ ×"Ò"ÜØ�D—G‘G�9Ð<Ø×"Ñ"Ñ%Ð%;ð=ó
ð 	
ð #×*Ñ*°%Ð*Ó8Ðà×Ñ×ÒÔ:¸9×EÒEÜ+¨IÓ6ˆØÔ'Ø%Ð4Ð4ô 7°y×7GÑ7GÓHˆØÒ$Ø$ |Õ3°d·g±gÕ=ˆHÜ˜×)Ñ)°Ð)Ó7Ó8¼IÐFXÓ<YÔYÜ$ ]¸kÔJØ×'Ñ'¨uÐ'Ó5°{ÐBÐBð "×#?Ð#?°KÐ?Ð?ä˜iÓ(€IØÒ¤Ð+=Ó!>Ä)ÈIÓBVÔ!VÜ! )¯W©W°kÓBÐBä.¨y×/?Ñ/?Ó@€IØÒÜØ�D—G‘G�9˜O¨D×,?Ñ,?Ñ+Bð C4ð 4ó
ð 	
ô ˜¨{Ô;ØÐ!Ð!r   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   rB  r   r™   rw   r   r   r   )r   s   "r   r   r     s!   € ÷ &ñ &˜Dð &¨Mð &ÀTñ &r   c               ó$  € V P                   ;'       g    RpVR8X  d   \        WR7      ^ ,          # VR8X  d=   V P                  '       g+   \        P                  ! VR7      V P
                  ,          pEM	VR8X  db   \        V P                  4      P                  4       pVP                  4       '       g(   \        RV P
                   RV P                  : R24      hM¡VR8X  d�   V P                  '       g   \        RV P
                   R24      h\        V P                  4      P                  4       pVP                  4       '       g(   \        RV P
                   RV P                  : R	24      hM\        R
V 24      hVP                  RRR7       V# )uE  Resolve (and create if needed) the workspace for a task.

``scratch``: ``<board-root>/workspaces/<id>/`` â€” path-stable across the
dispatcher and every profile worker. ``dir``: ``workspace_path``, created
if missing; MUST be absolute (relative paths would resolve against the
dispatcher's CWD â€” confused-deputy traversal). ``worktree``: a linked git
worktree; a repo-root ``workspace_path`` anchors ``<repo>/.worktrees/<id>``,
a concrete path is created/reused, none -> the board's ``default_workdir``
(raises if unset rather than guessing). Persist via ``set_workspace_path``.
rÆ   rÎ   )r™   rE  z! has non-absolute workspace_path z"; workspace paths must be absoluteÚdirz- has workspace_kind=dir but no workspace_pathzR; use an absolute path (relative paths are ambiguous against the dispatcher's CWD)zunknown workspace_kind: Tr
  )rÅ   rQ  rF   rX   Úworkspaces_rootrF  r   rL   rI  r·   r  )rB  r™   rÛ   r“   s   &$  r   Úresolve_workspacerV    sr  € ð ×Ñ×+Ð+ )€DØˆzÔÜ*¨4Ô=¸aÕ@Ð@ØˆyÔ ×!4×!4Ð!4Ü×Ò eÔ,¨t¯w©wÕ6ŠØ	�Ô	ô �×$Ñ$Ó%×0Ñ0Ó2ˆØ�}‰}�ŠÜØ˜Ÿ™�yÐ AØ×&Ñ&Ñ)Ð)KðMóð ð ð
 
�ŒØ×"×"Ð"Ü˜u T§W¡W IÐ-ZÐ[Ó\Ð\Ü�×$Ñ$Ó%×0Ñ0Ó2ˆØ�}‰}�ŠÜØ˜Ÿ™�yÐ AØ×&Ñ&Ñ)ð *NðOóð ð ô Ð3°D°6Ð:Ó;Ð;Ø‡G�G�D 4€GÔ(Ø€Hr   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r	   r3   r4   r5   r   ÚcolumnÚvaluer   rš   r   )r   s   "r   r   r   <  s9   € ÷ Vñ VÐ-ð V¸ð VÀSð VÐQTð VÐY]ñ Vr   c                óª   € \         P                  ! V 4      ;_uu_ 4        V P                  R V R2W134       RRR4       R#   + '       g   i     R# ; i)zUPDATE tasks SET z = ? WHERE id = ?N)rX   r  r9   )r3   r5   rX  rY  s   &&&&r   Ú_set_task_columnr[  <  s<   € Ü	�Š�t×	Õ	Ø�‰Ð(¨¨Ð0AÐBÀUÐDTÔU÷ 
×	×	Ò	ús   ŸAÁA	c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r	   r3   r4   r5   r   r
   rv   r   rš   r   )r   s   "r   r   r   A  s0   € ÷ Añ AÐ/ð A¸#ð AÀZð AÐTXñ Ar   c                ó2   € \        WR \        V4      4       R# )rF   N©r[  r   )r3   r5   r
   s   &&&r   Úset_workspace_pathr_  A  s   € Ü�TÐ$4´c¸$³iÖ@r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r3   r4   r5   r   rÏ   r   rš   r   )r   s   "r   r   r   E  s0   € ÷ Eñ EÐ,ð E°sð EÈð EÐQUñ Er   c                ó2   € \        WR \        V4      4       R# )rÏ   Nr^  )r3   r5   rÏ   s   &&&r   Úset_branch_namerb  E  s   € Ü�T M´3°{Ó3CÖDr   )Ú	kanban_db)rÆ   rÎ   r8   )DÚ__doc__Ú
__future__r   r�   rØ   ro   r,   rì   r   Úpathlibr   Útypingr   r   rŸ   ræ   r   Úhermes_cli.kanban_dbr   rÓ   r   Ú_TERMINAL_STATUSES_SQLr:   rÒ   r0   r=   r@   rA   rI   rK   rS   ri   rt   r€   r‡   rŒ   r‘   rÁ   rÇ   rÊ   rÝ   r×   rÔ   rÖ   r  r  r  r  r  r  r  r  r#  rç   r)  rŠ   r1  r4  r;  r@  rQ  rV  r[  r_  rb  Ú
hermes_clirc  rX   r   r   r   Ú<module>rk     s   ðñõ #ã 	Û Û Û Û Û Ý Ý Ý  Û å 7çÝ)à*Ð õ
Oð GÐ ð1à1GÐ0Hð Iðð ð bÐ õõ*Qð
 6Ð6LÐ5MÐNð õ
Oð
à/Ð0ð2ð ðà/Ð0ð2ð ðØQU÷õ(õBõ)õXõ:õ 2õ
HõV4õ,õ =÷@FõR&õRð, 2Ð ðJð õ:õ
õõ"õ8&õ"õIõ
3õ:õõõ!õ
õ&ðE"Àd÷ E"ðP&¸D÷ &õRVõ
AõE÷ (r   