§
    øžyj$  ã            
      ó  — d Z ddlmZ ddlmZmZ ddlZddlZddlm	Z	m
Z
mZ ddlmZ dZ ed¬	¦  «         G d
„ d¦  «        ¦   «         Z ed¬	¦  «         G d„ d¦  «        ¦   «         Zd5d„Zd6d„Zddddddddddœ	d7d,„Zd8d0„Zd9d2„Zd:d4„ZdS );uŽ  Kanban Swarm v1: thin swarm topology helpers on top of Kanban.

This module intentionally does not introduce a second scheduler. It writes a
small task graph into the existing Kanban kernel:

    planning root (completed immediately)
        â”œâ”€ parallel specialist workers (ready)
        â””â”€ verifier (todo until all workers done)
             â””â”€ synthesizer (todo until verifier done)

The shared blackboard is also deliberately low-tech: structured JSON comments on
the root task. That keeps all state in existing task_comments/task_events rows,
so the dashboard, notifier, slash command, and dispatcher keep working without a
new service.
é    )Úannotations)Ú	dataclassÚfieldN)ÚAnyÚIterableÚOptional)Ú	kanban_dbz[swarm:blackboard] T)Úfrozenc                  óp   — e Zd ZU dZded<   ded<   ded<    ee¬¦  «        Zded<   d	Zd
ed<   dZ	ded<   dS )ÚSwarmWorkerSpecz)A single parallel worker card in a swarm.ÚstrÚprofileÚtitleÚbody)Údefault_factoryú	list[str]Úskillsr   ÚintÚpriorityNzOptional[int]Úmax_runtime_seconds)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r   Úlistr   r   r   © ó    ú=/home/ragecks/.hermes/hermes-agent/hermes_cli/kanban_swarm.pyr   r      st   € € € € € € à3Ð3à€L€L�LØ€J€J�JØ€I€I�IØ˜¨dÐ3Ñ3Ô3€FÐ3Ð3Ð3Ñ3Ø€HÐÐÐÑØ)-ÐÐ-Ð-Ð-Ñ-Ð-Ð-r   r   c                  óD   — e Zd ZU dZded<   ded<   ded<   ded<   dd
„ZdS )ÚSwarmCreatedz%IDs produced by :func:`create_swarm`.r   Úroot_idr   Ú
worker_idsÚverifier_idÚsynthesizer_idÚreturnúdict[str, Any]c                óR   — | j         t          | j        ¦  «        | j        | j        dœS )N©r"   r#   r$   r%   )r"   r   r#   r$   r%   )Úselfs    r   Úas_dictzSwarmCreated.as_dict2   s/   € à”|Ý˜tœÑ/Ô/ØÔ+Ø"Ô1ð	
ð 
ð 	
r   N)r&   r'   )r   r   r   r   r   r+   r   r   r   r!   r!   )   s]   € € € € € € à/Ð/à€L€L�LØÐÐÑØÐÐÑØÐÐÑð
ð 
ð 
ð 
ð 
ð 
r   r!   Úvaluer   Ú
field_namer&   c                óZ   — | pd                      ¦   «         }|st          |› d�¦  «        ‚|S )NÚ z is required)ÚstripÚ
ValueError)r,   r-   Útexts      r   Ú_require_textr3   ;   s;   € ØˆK�R×ÒÑ Ô €DØð 6Ý˜JÐ4Ð4Ð4Ñ5Ô5Ð5Ø€Kr   r"   Úgoalc                ó8   — d| › d|                      ¦   «         › d�S )Nz7

## Swarm protocol
- Swarm root / shared blackboard: `zÈ`.
- Read sibling/parent handoffs from Kanban context before working.
- Put machine-readable facts in completion metadata.
- Put cross-worker notes on the root task using structured comments.
- Goal: Ú
©r0   )r"   r4   s     r   Ú_swarm_contextr8   B   s5   € ð	$Ø.5ð	$ð 	$ð
 —:’:‘<”<ð	$ð 	$ð 	$ðr   zVerify swarm outputszSynthesize swarm outputszswarm-orchestratorÚscratch)	Ú
root_titleÚverifier_titleÚsynthesizer_titleÚtenantÚ
created_byÚworkspace_kindÚworkspace_pathr   Úidempotency_keyÚconnúsqlite3.ConnectionÚworkersúIterable[SwarmWorkerSpec]Úverifier_assigneeÚsynthesizer_assigneer:   úOptional[str]r;   r<   r=   r>   r?   r@   r   r   rA   c               óx  — t          |d¦  «        }t          |d¦  «        }t          |d¦  «        }t          |¦  «        }|st          d¦  «        ‚t          |d¬¦  «        D ]7\  }}t          |j        d|› d�¦  «         t          |j        d|› d	�¦  «         Œ8t          j        | |p$d
|                     ¦   «         d         dd…         › �d|› �|	|	||||
|¬¦
  «
        }t          | |¦  «         
                    d¦  «        }t          |t          ¦  «        r}d„ | 
                    dg ¦  «        D ¦   «         }| 
                    d¦  «        }| 
                    d¦  «        }|r1|r/|r-t          ||t          |¦  «        t          |¦  «        ¬¦  «        S t          j        | |dd|t!          |¦  «        dœ¬¦  «         t#          ||¦  «        }g }|D ]_}t          j        | |j        |j        pd|z   |j        |	|g||j        p||
||j        pd|j        ¬¦  «        }|                     |¦  «         Œ`d|z   }t          j        | ||||	||||
|dg¬¦  «        }d|z   }t          j        | ||||	|g|||
|d g¬¦  «        }t          ||||¦  «        }t/          | ||	d|                     ¦   «         d|iz  ¬!¦  «         |S )"a  Create a durable Kanban swarm graph.

    The returned graph is immediately dispatchable: the planning root is marked
    ``done`` with topology metadata, parallel workers are ``ready``, the verifier
    waits for every worker, and the synthesizer waits for the verifier.
    r4   rF   rG   zat least one worker is requiredé   )Ústartzworkers[z	].profilez].titlezSwarm: r   NéP   z¥Kanban Swarm v1 planning/root card. This card is completed immediately so parallel workers can start while it remains the shared blackboard and audit anchor.

Goal:
)	r   r   Úassigneer>   r=   r   rA   r?   r@   Útopologyc                ó0   — g | ]}|¯t          |¦  «        ‘ŒS r   )r   )Ú.0Úxs     r   ú
<listcomp>z create_swarm.<locals>.<listcomp>†   s#   € ÐJÐJÐJ ÈÐJ•c˜!‘f”fÐJÐJÐJr   r#   r$   r%   r)   z;Swarm topology planned; root remains the shared blackboard.Úkanban_swarm_v1)Úkindr4   Úworker_count)ÚsummaryÚmetadatar/   )r   r   rM   r>   Úparentsr=   r   r?   r@   r   r   zµReview every worker handoff and blackboard update. Gate the swarm: complete only with metadata {"gate": "pass"} when evidence is sufficient; otherwise block with exact missing work.zrequesting-code-review)
r   r   rM   r>   rX   r=   r   r?   r@   r   zwSynthesize the verified worker outputs into the final deliverable. Do not start until the verifier has passed the gate.Ú	humanizer)ÚauthorÚkeyr,   )r3   r   r1   Ú	enumerater   r   ÚkbÚcreate_taskÚ
splitlinesÚlatest_blackboardÚgetÚ
isinstanceÚdictr!   r   Úcomplete_taskÚlenr8   r   r   r   r   ÚappendÚpost_blackboard_updater+   )rB   r4   rD   rF   rG   r:   r;   r<   r=   r>   r?   r@   r   rA   Úworker_specsÚiÚspecÚrootÚexistingr#   r$   r%   Úcontext_suffixÚ	worker_idÚverifier_bodyÚverifierÚsynthesizer_bodyÚsynthesizerÚcreateds                                r   Úcreate_swarmrt   M   s±  € õ0 ˜˜vÑ&Ô&€DÝ%Ð&7Ð9LÑMÔMÐÝ(Ð)=Ð?UÑVÔVÐÝ˜‘=”=€LØð <ÝÐ:Ñ;Ô;Ð;Ý˜\°Ð3Ñ3Ô3ð 9ð 9‰ˆˆ4Ý�d”lÐ$;¨qÐ$;Ð$;Ð$;Ñ<Ô<Ð<Ý�d”jÐ"7¨QÐ"7Ð"7Ð"7Ñ8Ô8Ð8Ð8åŒ>ØØÐAÐA d§o¢oÑ&7Ô&7¸Ô&:¸3¸B¸3Ô&?ÐAÐAðð ðð ð
 ØØØØ'Ø%Ø%ðñ ô €Dõ* !  tÑ,Ô,×0Ò0°Ñ<Ô<€HÝ�(�DÑ!Ô!ð 
ØJÐJ h§l¢l°<ÀÑ&DÔ&DÐJÑJÔJˆ
Ø—l’l =Ñ1Ô1ˆØ!ŸšÐ&6Ñ7Ô7ˆØð 	˜+ð 	¨.ð 	ÝØØ%Ý Ñ,Ô,Ý" >Ñ2Ô2ð	ñ ô ð õ ÔØØØMà%ØÝ Ñ-Ô-ð
ð 
ð		ñ 	ô 	ð 	õ $ D¨$Ñ/Ô/€NØ€JØð %ð %ˆÝ”NØØ”*Ø”)�/˜r ^Ñ3Ø”\Ø!Ø�FØØ”]Ð. hØ)Ø)Ø”;Ð& $Ø $Ô 8ð
ñ 
ô 
ˆ	ð 	×Ò˜)Ñ$Ô$Ð$Ð$ð	?ð ñ	ð õ Œ~ØØØØ"ØØØØØ%Ø%Ø(Ð)ðñ ô €Hð	?à
ñ	ð õ
 ”.ØØØØ%ØØ�
ØØØ%Ø%Øˆ}ðñ ô €Kõ ˜4 ¨X°{ÑCÔC€GÝØØØØØ�oŠoÑÔ 6¨4 .Ñ0ðñ ô ð ð €Nr   rZ   r[   r   c               óÖ   — t          |d¦  «         t          |d¦  «        }t          |d¦  «        }t          j        ||dœdd¬¦  «        }t          j        | ||t
          |z   ¬¦  «        S )	z:Append one structured update to the swarm root blackboard.r"   rZ   r[   )r[   r,   FT)Úensure_asciiÚ	sort_keys)rZ   r   )r3   ÚjsonÚdumpsr]   Úadd_commentÚBLACKBOARD_PREFIX)rB   r"   rZ   r[   r,   Úpayloads         r   rg   rg   á   sq   € õ �'˜9Ñ%Ô%Ð%Ý˜6 8Ñ,Ô,€FÝ
˜˜UÑ
#Ô
#€CÝŒj ¨uÐ5Ð5ÀEÐUYÐZÑZÔZ€GÝŒ>˜$ °Õ=NÐQXÑ=XÐYÑYÔYÐYr   r'   c                ó¼  — i }i }t          j        | |¦  «        D ]º}|j        pd}|                     t          ¦  «        sŒ&	 t          j        |t          t          ¦  «        d…         ¦  «        }n# t
          j        $ r Y Œgw xY w| 	                    d¦  «        }t          |t          ¦  «        r|sŒ˜| 	                    d¦  «        ||<   |j        ||<   Œ»|r||d<   |S )zÁMerge structured blackboard comments on a root card.

    Later comments replace earlier values for the same key. ``_authors`` records
    the author of the winning value for traceability.
    r/   Nr[   r,   Ú_authors)r]   Úlist_commentsr   Ú
startswithr{   rx   Úloadsre   ÚJSONDecodeErrorra   rb   r   rZ   )rB   r"   ÚmergedÚauthorsÚcommentr   r|   r[   s           r   r`   r`   ò   s  € ð  €FØ €GÝÔ# D¨'Ñ2Ô2ð &ð &ˆØŒ|Ð!˜rˆØ�ŠÕ0Ñ1Ô1ð 	Øð	Ý”j ¥cÕ*;Ñ&<Ô&<Ð&=Ð&=Ô!>Ñ?Ô?ˆGˆGøÝÔ#ð 	ð 	ð 	ØˆHð	øøøà�kŠk˜%Ñ Ô ˆÝ˜#�sÑ#Ô#ð 	¨3ð 	ØØ—k’k 'Ñ*Ô*ˆˆs‰Ø”~ˆ�‰ˆØð %Ø$ˆˆzÑØ€Ms   Á.A0Á0BÂBÚrawc                óT  — d„ |                       dd¦  «        D ¦   «         }t          |¦  «        dk     rt          d¦  «        ‚g }t          |¦  «        dk    r-|d         r%d„ |d                               d¦  «        D ¦   «         }t          |d         |d	         |d	         |¬
¦  «        S )z:Parse CLI ``--worker profile:title[:skill,skill]`` values.c                ó6   — g | ]}|                      ¦   «         ‘ŒS r   r7   )rP   Úps     r   rR   z$parse_worker_arg.<locals>.<listcomp>  s    € Ð2Ð2Ð2˜1ˆQ�WŠW‰YŒYÐ2Ð2Ð2r   ú:é   z9worker must be profile:title or profile:title:skill,skillé   c                ó^   — g | ]*}|                      ¦   «         ¯|                      ¦   «         ‘Œ+S r   r7   )rP   Úss     r   rR   z$parse_worker_arg.<locals>.<listcomp>  s-   € ÐFÐFÐF ¸A¿GºG¹I¼IÐF�!—'’'‘)”)ÐFÐFÐFr   ú,r   rJ   )r   r   r   r   )Úsplitre   r1   r   )r†   Úpartsr   s      r   Úparse_worker_argr’     s¦   € ð 3Ð2 §	¢	¨#¨qÑ 1Ô 1Ð2Ñ2Ô2€EÝ
ˆ5�z„z�A‚~€~ÝÐTÑUÔUÐUØ€FÝ
ˆ5�z„z�Q‚€˜5 œ8€ØFÐF U¨1¤X§^¢^°CÑ%8Ô%8ÐFÑFÔFˆÝ 5¨¤8°5¸´8À%ÈÄ(ÐSYÐZÑZÔZÐZr   )r,   r   r-   r   r&   r   )r"   r   r4   r   r&   r   )rB   rC   r4   r   rD   rE   rF   r   rG   r   r:   rH   r;   r   r<   r   r=   rH   r>   r   r?   r   r@   rH   r   r   rA   rH   r&   r!   )rB   rC   r"   r   rZ   r   r[   r   r,   r   r&   r   )rB   rC   r"   r   r&   r'   )r†   r   r&   r   )r   Ú
__future__r   Údataclassesr   r   rx   Úsqlite3Útypingr   r   r   Ú
hermes_clir	   r]   r{   r   r!   r3   r8   rt   rg   r`   r’   r   r   r   ú<module>r˜      sÁ  ððð ð  #Ð "Ð "Ð "Ð "Ð "à (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø €€€Ø €€€Ø *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *à &Ð &Ð &Ð &Ð &Ð &à)Ð ð €�$ÐÑÔð.ð .ð .ð .ð .ñ .ô .ñ Ôð.ð €�$ÐÑÔð
ð 
ð 
ð 
ð 
ñ 
ô 
ñ Ôð
ð"ð ð ð ðð ð ð ð$ !%Ø0Ø7Ø Ø*Ø#Ø$(ØØ%)ðQð Qð Qð Qð Qð QðhZð Zð Zð Zð"ð ð ð ð6	[ð 	[ð 	[ð 	[ð 	[ð 	[r   