
    FjR                   v   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZmZ ddlmZ ddlmZ ddlmZmZmZ d	d
ddddddZdbdZdcdZdddZdedZdfd!Zdgd#Zdhd%Zdid)Zdjd+Z dkd,Z!djd-Z"dld0Z#djd1Z$djd2Z%djd3Z&djd4Z'djd5Z(djd6Z)djd7Z*dmd8Z+djd9Z,djd:Z-djd;Z.djd<Z/djd=Z0djd>Z1djd?Z2djd@Z3djdAZ4djdBZ5djdCZ6djdDZ7djdEZ8djdFZ9djdGZ:dndIZ;djdJZ<djdKZ=djdLZ>djdMZ?djdNZ@djdOZAdjdPZBdjdQZCdjdRZDdjdSZEdjdTZFdjdUZGdjdVZHdjdWZIdjdXZJdjdYZKdjdZZLdjd[ZMdjd\ZNdjd]ZOdjd^ZPd_ZQdodaZRdS )pu)  CLI for the Hermes Kanban board — ``hermes kanban …`` subcommand.

Exposes the full Kanban command surface documented in the design spec
(``docs/hermes-kanban-v1-spec.pdf``).  All DB work is delegated to
``kanban_db``.  This module adds:

  * Argparse subcommand construction (``build_parser``).
  * Argument dispatch (``kanban_command``).
  * Output formatting (plain text + ``--json``).
  * A short shared helper that parses a single slash-style string
    (used by ``/kanban …`` in CLI and gateway) and forwards it to the
    argparse surface.
    )annotationsN)Path)AnyOptional)	kanban_db)kanban_swarm)get_active_profile_nameget_profile_dirseed_profile_skillsu   ◻u   ▶   ●u   ⏱u   ⊘u   ✓u   —)todoreadyrunning	scheduledblockeddonearchivedtsOptional[int]returnstrc                X    | sdS t          j        dt          j        |                     S )N z%Y-%m-%d %H:%M)timestrftime	localtime)r   s    0/usr/local/lib/hermes-agent/hermes_cli/kanban.py_fmt_tsr   .   s,     r=)4>"+=+=>>>    tkb.Taskc           
         t                               | j        d          }| j        pd}| j        rd| j         dnd}| d| j         d| j        dd|d	| d| j         
S )
N?(unassigned) []r      8s20s)_STATUS_ICONSgetstatusassigneetenantidtitle)r    iconr.   r/   s       r   _fmt_task_liner3   4   s    QXs++Dz+^H!"1!(rFMMQTMMQXMMMHMM&MMAGMMMr   dict[str, Any]c                l   i d| j         d| j        d| j        d| j        d| j        d| j        d| j        d| j        d	| j        d
| j	        d| j
        d| j        d| j        d| j        d| j        d| j        rt!          | j                  ng d| j        | j        | j        | j        dS )Nr0   r1   bodyr.   r-   priorityr/   workspace_kindworkspace_pathbranch_name
created_by
created_at
started_atcompleted_atresultskillsmax_retries)
session_idworkflow_template_idcurrent_step_key)r0   r1   r6   r.   r-   r7   r/   r8   r9   r:   r;   r<   r=   r>   r?   r@   listrA   rB   rC   rD   )r    s    r   _task_to_dictrF   ;   s+   ad 	 	AJ	
 	!( 	AJ 	!( 	!* 	!* 	q} 	al 	al 	al 	 	!(  	AH4$qx..."!" 	q}#$ l ! 6.)   r   argsargparse.NamespaceOptional[dict[str, str]]c                p    t          | dd           }t          | dd           }|d u |d u k    rd S |i S ||dS )N
state_type
state_name)rK   rL   )getattr)rG   stsns      r   _run_state_kwargsrP   T   sT    	|T	*	*B	|T	*	*B
d
d
##t	z	B///r   valuetuple[str, Optional[str]]c                x   | sdS |                                  }|dv r|dfS dD ]\  }}|                    |          s|t          |          d                                          }|st          j        d| d          |t
          j                            |          fc S t          j        d| d          )	zParse ``--workspace`` into ``(kind, path|None)``.

    Accepts: ``scratch``, ``worktree``, ``worktree:<path>``, ``dir:<path>``.
    )scratchN>   rT   worktreeN))zdir:dir)z	worktree:rU   z--workspace z  requires a path after the colonzunknown --workspace value z7: use scratch, worktree, worktree:<path>, or dir:<path>)strip
startswithlenargparseArgumentTypeErrorospath
expanduser)rQ   vprefixkindr]   s        r   _parse_workspace_flagrb   ^   s    
  !  A###4yD 0 0||F## 	V$$&& 	,GvGGG   bg((..////

$	)U 	) 	) 	)  r   Optional[str]c                   | dS |                                  }|st          j        d          |                    d          rt          j        d          t	          d |D                       rt          j        d          |S )zBNormalize an optional branch name from ``kanban create --branch``.Nz"--branch requires a non-empty name-z --branch must not start with '-'c              3  >   K   | ]}|                                 V  d S N)isspace).0chs     r   	<genexpr>z%_parse_branch_flag.<locals>.<genexpr>   s*      
)
)B2::<<
)
)
)
)
)
)r   z$--branch must not contain whitespace)rW   rZ   r[   rX   any)rQ   branchs     r   _parse_branch_flagrn   w   s    }t[[]]F O()MNNN M()KLLL

)
)&
)
)
))) Q()OPPPMr   tuple[bool, str]c                 L   	 ddl m}  n# t          $ r Y dS w xY w	  |             }n# t          $ r Y dS w xY w	 ddlm}  |            }t          |                    di                               dd                    }n# t          $ r d}Y nw xY w|r
|rdd| d	fS |r|sd
S dS )u  Return ``(running, message)``.

    - ``running=True``: a gateway is alive for this HERMES_HOME and its
      config has ``kanban.dispatch_in_gateway`` on (default). Message
      is a short status line.
    - ``running=False``: either no gateway is running, or the gateway
      is running but the config flag is off. Message is human guidance
      explaining the next step.

    Used by ``hermes kanban create`` (and callers) to warn when a task
    will sit in ``ready`` because nothing is there to pick it up.
    Defensive against import failures and config-read errors — if the
    probe itself errors, we return ``(True, "")`` so we don't spam
    false warnings (better to miss a warning than to cry wolf).
    r   )get_running_pid)Tr   load_configkanbandispatch_in_gatewayTzgateway pid=z, dispatch enabled)Fu   Gateway is running but kanban.dispatch_in_gateway=false in config.yaml — the task will sit in 'ready' until you flip it back on and restart the gateway, OR run the legacy standalone daemon (`hermes kanban daemon --force`).)Fu   No gateway is running — the task will sit in 'ready' until you start it. Run:
    hermes gateway start
The gateway hosts an embedded dispatcher (tick interval 60s by default); your task will be picked up on the next tick after the gateway comes up.)gateway.statusrq   	Exceptionhermes_cli.configrs   boolr,   )rq   pidrs   cfgdispatch_ons        r   _check_dispatcher_presencer}      s3    2222222   zzo   zz111111kmm3778R00445JDQQRR     >{ ><S<<<==
 
; 

 
 s*   	 

& 
44AB   BBparent_subparsersargparse._SubParsersActionargparse.ArgumentParserc           	     P'   |                      ddd          }|                    dddd	           |                    d
          }|                     dd           |                     ddd          }|                    d          }|                     ddgd          }|                    dd           |                    ddd           |                     ddgd          }|                    d d!           |                    d"dd#$           |                    d%dd&$           |                    d'dd($           |                    d)dd*$           |                    d+dd,           |                    d-dd.$           |                     d/d0d1gd2          }|                    d            |                    d3dd4           |                     d5d6gd7          }|                    d            |                     d8d9gd:           |                     d;d<          }	|	                    d            |	                    d=d>           |                     d?d@          }
|
                    d            |
                    dAdBddCD           |                     ddE          }|                    dFdG           |                    dHddI$           |                    dJddK$           |                    dLdMg dNO           |                    dPdQdR$           |                    dSddT$           |                    dUddV$           |                    dWt          dXdYZ           |                    d[dd\           |                    d]dd^$           |                    d_dd`$           |                    dadbdc$           |                    dddMg dedfg           |                    dht          ddidjt          j         dkl           |                    dmt          t          j                  dndop           |                    dddq           |                     drds          }|                    dtdu           |                    dvdMg dwdxy           |                    dzd{d|}           |                    d~d{d}           |                    dUddV$           |                    dWt          dXdYZ           |                    dadd$           |                    d]dd$           |                    dddq           |                     ddgd          }|                    ddd           |                    dJd           |                    ddt          t          j                             |                    dUd           |                    ddd$           |                    ddd           |                    dd           |                    ddt          t          j	        
                                          d           |                    dddd	           |                    ddddd           |                     d8d          }|                    d           |                    dd           |                    ddddp           |                    dddd	           |                     dd          }|                    d           |                    dd           |                     dd          }|                    d           |                    ddd$           |                     dd          }|                    d           |                    dd           |                    ddd           |                    ddd$           |                     ddgd          }|                    dg dddp           |                    ddd$           |                    ddd           |                     dd          }|                    d           |                    d           |                     dd          }|                    d           |                    d           |                     dd          }|                    d           |                    dt          t          j        dZ           |                     dd          }|                    d           |                    dddìĦ           |                    dddƬ$           |                    dt          ddȬZ           |                     ddʬ          }|                    ddd̬Ħ           |                    dddά$           |                    dddЬ$           |                    dddҬ$           |                     ddԬ          }|                    d           |                    dd{dլ}           |                    ddd֬$           |                    ddd׬$           |                     dd٬          }|                    d           |                    dddܬĦ           |                    ddddެD           |                     dd          }|                    d           |                    dddĦ           |                    ddddD           |                     dd          }|                    ddd$           |                    dd¬           |                     dd          }|                    d           |                    dddĦ           |                    ddddD           |                    ddd           |                    ddd           |                    dddd           |                     dd          }|                    dddĦ           |                    ddddd           |                     dd          }|                    d           |                    dt          d           |                     dd          }|                    ddd            |                    dt          ddZ           |                    dt          t          j        dt          j         dZ           |                    dd           |                     dd          } |                     dt          dd	Z           |                     dt          dd
Z           |                     dt          t          j                   |                     ddd$           |                     dddd           |                     ddt          j                   |                     dd          }!|!                    dJdd$           |!                    dUdd$           |!                    ddd$           |!                    dt          ddZ           |                     dd          }"|"                    dd           |                     dd          }#|#                    d           |#                    dd{           |#                    dd{           |#                    dd           |#                    d d           |#                    d!dd"$           |                     d#d$          }$|$                    ddBd%           |$                    dd           |                     d&d'          }%|%                    d           |%                    dd{           |%                    dd{           |%                    dd           |                     d(d)          }&|&                    d           |&                    d*t          dd+Z           |                     d,d-          }'|'                    d           |'                    dd           |'                    dddd.p           |'                    dddd	           |                     d/d0          }(|(                    d           |(                    d1dd2$           |                     d3d4          })|)                    dd           |                     d5d6          }*|*                    d           |                     d7d8          }+|+                    ddBdd9D           |+                    dd:dd;           |+                    dUdd<$           |+                    ddd=$           |+                    ddd>           |                     d?d@          },|,                    ddBddAD           |,                    dd:ddB           |,                    dUdd<$           |,                    dddC$           |,                    ddd>           |                     dDdE          }-|-                    dFt          dGdHZ           |-                    dIt          dGdJZ           |                    |K           |S (L  zAttach the ``kanban`` subcommand tree under an existing subparsers.

    Returns the top-level ``kanban`` parser so caller can ``set_defaults``.
    rt   z:Multi-profile collaboration board (tasks, links, comments)a7  Durable SQLite-backed task board shared across Hermes profiles. Tasks are claimed atomically, can depend on other tasks, and are executed by a named profile in an isolated workspace. See https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban or docs/hermes-kanban-v1-spec.pdf for the full design.)helpdescriptionz--boardNz<slug>zBoard slug to operate on. Defaults to the current board (set via `hermes kanban boards switch <slug>` or the HERMES_KANBAN_BOARD env var). Use `hermes kanban boards list` to see all boards.)defaultmetavarr   kanban_actiondestinitz(Create kanban.db if missing (idempotent))r   boardsz9Manage kanban boards (one board per project / workstream)u  Boards let you separate unrelated streams of work (projects, repos, domains) into isolated queues. Each board has its own DB, workspaces directory, and dispatcher loop — tasks on one board cannot collide with tasks on another. The first board is 'default' and always exists.boards_actionrE   lsz List all boards with task counts)aliasesr   z--json
store_true)actionz--allzInclude archived boards too)r   r   createnewzCreate a new boardslugz*Board slug (kebab-case, e.g. atm10-server)z--namez<Human-readable display name (defaults to Title Case of slug))r   r   z--descriptionzOptional descriptionz--iconz9Optional emoji or single-character icon for the dashboardz--colorz5Optional hex color (e.g. '#8b5cf6') for the dashboardz--switchz)Switch to the new board after creating itz--default-workdirz6Default workspace path for tasks created on this boardrmremovedeletez#Archive (default) or delete a boardz--deletezxHard-delete the board directory instead of archiving it. Default is to move it to boards/_archived/ so it's recoverable.switchusez-Set the active board for subsequent CLI callsshowcurrentz%Print the currently-active board slugrenamez@Change a board's human-readable display name (slug is immutable)namezNew display nameset-default-workdirz3Set the default workspace path for tasks on a boardr]   r#   z7Absolute path to use as default workdir. Omit to clear.)nargsr   r   zCreate a new taskr1   z
Task titlez--bodyzOptional opening postz
--assigneezProfile name to assignz--parentappendzParent task id (repeatable))r   r   r   z--workspacerT   zDscratch | worktree | worktree:<path> | dir:<path> (default: scratch)z--branchz/Branch name for worktree tasks, e.g. wt/t6-wirez--tenantzTenant namespacez
--priorityr   zPriority tiebreaker)typer   r   z--triageuJ   Park in triage — a specifier will flesh out the spec and promote to todoz--idempotency-keyzkDedup key. If a non-archived task with this key exists, its id is returned instead of creating a duplicate.z--max-runtimezPer-task runtime cap. Accepts seconds (300) or durations (90s, 30m, 2h, 1d). When exceeded, the dispatcher SIGTERMs (then SIGKILLs) the worker and re-queues the task.z--created-byuserz0Author name recorded on the task (default: user)z--skillr@   zSkill to force-load into the worker (repeatable). Appended to the built-in kanban-worker skill. Example: --skill translation --skill github-code-review)r   r   r   r   z--max-retriesNu   Per-task override for the consecutive-failure circuit breaker. Trip on the Nth failure — e.g. --max-retries 1 blocks on the first failure (no retries), --max-retries 3 allows two retries. Omit to use the dispatcher's kanban.failure_limit config (default z).)r   r   r   r   z--initial-statusr   zInitial card status. Use 'blocked' for cards that require immediate human ops (R3 gate) to skip the brief running-to-blocked transition.)choicesr   r   zEmit JSON outputswarmuN   Create a Kanban Swarm v1 graph (parallel workers → verifier → synthesizer)goalzSwarm goal / final outcomez--workerzPROFILE:TITLE[:SKILL,SKILL]z!Parallel worker card (repeatable))r   r   r   r   z
--verifierTzVerifier profile)requiredr   z--synthesizerzSynthesizer/writer profilezCreator/anchor profilezDedup key for the root cardz
List tasksz--minez%Filter by $HERMES_PROFILE as assignee)r   z--status)r   r   z	--sessionzZFilter by originating chat/agent session id (set on tasks created from inside an ACP loop)z
--archivedzInclude archived tasksz--sortz/Sort order for listed tasks (default: priority))r   r   r   z--workflow-template-idIDz0Restrict to tasks with this workflow_template_idz
--step-keyrD   KEYz,Restrict to tasks with this current_step_key)r   r   r   r   z"Show a task with comments + eventstask_idz--state-type)r-   outcomez9With --state-name: filter listed runs by task_runs columnz--state-nameVALUEz;With --state-type: keep runs whose column equals this valueassignzAssign or reassign a taskprofilez$Profile name (or 'none' to unassign)reclaimz0Release an active worker claim on a running taskz--reasonz7Human-readable reason (recorded on the reclaimed event)reassignzCReassign a task to a different profile, optionally reclaiming firstz(New profile name (or 'none' to unassign)z	--reclaimzIRelease any active claim before reassigning (required if task is running)diagnosticsdiagz,List active diagnostics on the current boardz
--severitywarningerrorcriticalz/Only show diagnostics at or above this severityz--taskz%Only show diagnostics for one task idz9Emit JSON (structured) instead of the default human tablelinkzAdd a parent->child dependency	parent_idchild_idunlinkz!Remove a parent->child dependencyclaimz>Atomically claim a ready task (prints resolved workspace path)z--ttlz#Claim TTL in seconds (default: 900)commentzAppend a commenttext+zComment body)r   r   z--authorz0Author name (default: $HERMES_PROFILE or 'user')z	--max-lenz4Trim the stored comment body to this many characterscompletezMark one or more tasks donetask_idsz;One or more task ids (only --result applies to all of them)z--resultzResult summaryz	--summaryzSStructured handoff summary for downstream tasks. Falls back to --result if omitted.z
--metadatazlJSON dict of structured facts (e.g. '{"changed_files": [...], "tests_run": 12}'). Stored on the closing run.editz1Edit recovery fields on an already-completed taskz+Backfilled task result text for a done taskz>Structured handoff summary. Falls back to --result if omitted.zCJSON dict of structured facts to store on the latest completed run.blockzMark one or more tasks blockedreason*z#Reason (also appended as a comment)z--idsz=Additional task ids to block with the same reason (bulk mode)schedulezFPark one or more tasks in Scheduled (waiting on time, not human input)z/Reason/timing note (also appended as a comment)z@Additional task ids to schedule with the same reason (bulk mode)unblockz3Return one or more blocked/scheduled tasks to readyu[   Optional reason/note — recorded as a comment before unblocking. Quote multi-word reasons.)r   promotezEManually move one or more todo/blocked tasks to ready (recovery path)z4Audit-trail reason (recorded on the task_events row)z?Additional task ids to promote with the same reason (bulk mode)z--forcez=Promote even if parent dependencies are not yet done/archivedz	--dry-runz-Validate the promotion without mutating statejsonz!Emit machine-readable JSON result)r   r   r   archivezArchive one or more tasksz"Task ids to archive (default mode)z--rm	purge_idsz;Permanently delete already-archived task ids from the board)r   r   r   r   tailzFollow a task's event streamz
--intervalg      ?)r   r   dispatchz@One dispatcher pass: reclaim stale, promote ready, spawn workersz<Don't actually spawn processes; just print what would happenz--maxzCap number of spawns this passz--failure-limitzrAuto-block a task after this many consecutive non-success attempts (spawn_failed, timed_out, or crashed; default: )daemonuN   DEPRECATED — dispatcher now runs in the gateway. Use `hermes gateway start`.g      N@z,Seconds between dispatch ticks (default: 60)zCap number of spawns per tickz	--pidfilez,Write the daemon's PID to this file on startz	--verbosez-vz!Log each tick's outcome to stdoutwatchz8Live-stream task_events to the terminal (Ctrl+C to exit)z3Only show events for tasks assigned to this profilez*Only show events from tasks in this tenantz--kindsz[Comma-separated event kinds to include (e.g. 'completed,blocked,gave_up,crashed,timed_out')g      ?z'Poll interval in seconds (default: 0.5)statsz3Per-status + per-assignee counts + oldest-ready agenotify-subscribeziSubscribe a gateway source to a task's terminal events (used by /kanban subscribe in the gateway adapter)z
--platform)r   z	--chat-idz--thread-idz	--user-idz--notifier-profilezNProfile gateway that owns/delivers this subscription (default: active profile)notify-listz>List notification subscriptions (optionally for a single task))r   r   notify-unsubscribez)Remove a gateway subscription from a tasklogzAPrint the worker log for a task (from <kanban-root>/kanban/logs/)z--tailzOnly print the last N bytesrunszUShow attempt history for a task (one row per run: profile, outcome, elapsed, summary)z2With --state-name: filter runs by task_runs column	heartbeatzBEmit a heartbeat event for a running task (worker liveness signal)z--notez3Optional short note attached to the heartbeat event	assigneeszoList known profiles + per-profile task counts (union of ~/.hermes/profiles/ and current assignees on the board)contextz[Print the full context a worker sees for a task (title + body + parent results + comments).specifyzFlesh out a triage-column task into a concrete spec (title + body) and promote it to todo. Uses the auxiliary LLM configured under auxiliary.triage_specifier.z3Task id to specify (required unless --all is given)
all_triagez1Specify every task currently in the triage columnz7When used with --all, restrict the sweep to this tenantzSAuthor name recorded on the audit comment (default: $HERMES_PROFILE or 'specifier')z'Emit one JSON object per task on stdout	decomposezDecompose a triage-column task into a graph of child tasks routed to specialist profiles by description. Falls back to specify-style single-task promotion when the task doesn't benefit from fan-out. Uses auxiliary.kanban_decomposer.z5Task id to decompose (required unless --all is given)z3Decompose every task currently in the triage columnzTAuthor name recorded on the audit comment (default: $HERMES_PROFILE or 'decomposer')gczBGarbage-collect archived-task workspaces, old events, and old logsz--event-retention-days   zEDelete task_events older than N days for terminal tasks (default: 30)z--log-retention-daysz7Delete worker log files older than N days (default: 30))_kanban_parser)
add_parseradd_argumentadd_subparsersintkbDEFAULT_FAILURE_LIMITsortedVALID_INITIAL_STATUSESVALID_STATUSESVALID_SORT_ORDERSkeysDEFAULT_CLAIM_TTL_SECONDSfloatDEFAULT_SPAWN_FAILURE_LIMITrZ   SUPPRESSset_defaults).r~   kanban_parsersubp_boards
boards_subb_listb_createb_rmb_switchb_renameb_set_wdp_createp_swarmp_listp_showp_assign	p_reclaim
p_reassignp_diagp_linkp_unlinkp_claim	p_comment
p_completep_editp_block
p_schedule	p_unblock	p_promote	p_archivep_tailp_dispp_daemonp_watchp_statsp_nsubp_nlistp_nrmp_logp_runsp_hbp_asgp_ctx	p_specifyp_decomposep_gcs.                                                 r   build_parserr     sW   
 &00IE	 1 
 
M  !  
 
 
 
&
&O
&
<
<C NN6 JNKKK ~~HG	  
 
H ((o(>>J""/ #  F 666
:  < < < $$5'! %  H &K  M M M(D]  _ _ _/45  7 7 7(DZ  \ \ \)TV  X X X*\J  L L L-tW  Y Y Y   x*2 !  D 	fj]  ^ ^ ^ $$5'< %  H &!!!4    
 $$O %  H &!!!&'9:::$$B %  H &!!!&TX  Z Z Z ~~h-@~AAH'555(D7NOOO,;STTT*Xr<  > > >- 4  5 5 5 *dP  R R R*d9KLLL,S!BWXXX*\k  m m m-t U  V V V /4 9  : : :
 .&Q  S S S)Hbx P  Q Q Q
 /T"% H ,.+C H  H  H  I I I ,"()B"C"C"+ R  S S S (<>PQQQ nn]   G &BCCC-0     ;MNNN4>Z[[[T8JKKKCAVWWW<TUUU,dA^___,=OPPP ^^FTF^FFF
D  F F F
d333

D &r'8 9 9  ; ; ;

D111
TN  O O O \5  7 7 7
666
r+002233>	      ?	     ;     ^^F)M^NNF
	"""
666
%H	     J	     ~~h-H~IIH)$$$)*PQQQ ?   I 9%%%DF    
 R    J I&&&7     LX     DF     ^^;   F
 000>	     4    
 H     ^^F)I^JJF
$$$

###~~h-P~QQH+&&&*%%% nnM   G ###sB4PC  E E E y/ABBI9%%%6>BBB:t R  T T T;S$ V  X X X 
1NOOJJc!^  ` ` `J;KLLLK"F  G G G L$"S  T T T ^^@   F 	"""
:    
 M    
 R     nnW+KnLLG###3XYYYT]  _ _ _ 
1yzzJI&&&HC6ghhhG3!c  e e e y/deeIj    
 :S111T   I 9%%%C    
 N	     L    
 <    
 0	     y/JKKI:S D  F F FJ     ^^F)G^HHF
	"""
5#>>> ^^O   F L[  ] ] ]
c4=  ? ? ?
) " >qOQOmq q q  r r r 666 ~~]   H ,UDM  O O O'T>  @ @ @+#"$"@  B B B+tM  O O O+tLB  D D D
 )L'0  2 2 2 nnG   G tS  U U UTJ  L L LDU  V V V E3G  I I I nnK   G ,777 ^^B   F
 	"""
t444
d333
t444
T222
d]    
 nnM   G #t<<<,777NN8   E 
y!!!	|d333	{T222	}d333 NNP   E 
y!!!	xc49  ; ; ; ^^*   F
 	"""
666
%A	     J	     >>Q   D 	i   hP  R R R NNQ   E
 
x555 NN;   E
 
y!!! @   I B	     @	     F    
 9     6     ..G !  K D	     B	     F    
 :     6     >>W   D 	.S"b  d d d,3T  V V V m<<<r   r   c                r  	
 t          | dd          }|sEt          | dd          }||                                 nt          dt          j                   dS |dk    rt          |           S t          | dd          }t          j                            d	          	d

d;	
fd}|r	 t          j
        |          }n6# t          $ r)}t          d| t          j                   Y d}~dS d}~ww xY w|st          dt          j                   dS |t          j        k    r8t          j        |          s$t          d|d| dt          j                   dS |t          j        d	<   d
	 t          j                     n@# t          $ r3}t          d| t          j                    |             Y d}~dS d}~ww xY wi dt           dt"          dt$          dt&          dt&          dt(          dt*          dt,          dt.          d t0          d!t0          d"t2          d#t4          d$t6          d%t8          d&t:          d't<          i d(t>          d)t@          d*tB          d+tD          d,tF          d-tH          d.tJ          d/tL          d0tN          d1tP          d2tR          d3tT          d4tV          d5tX          d6tZ          d7t\          d8t^          t`          tb          td          tf          d9}|                    |          }|s*t          d:|t          j                    |             dS 	 ti           ||           pd           |             S # t          tj          f$ r=}t          d| t          j                    |             Y d}~ |             dS d}~ww xY w#  |             w xY w)<u   Entry point from ``hermes kanban …`` argparse dispatch.

    Returns a shell-style exit code (0 on success, non-zero on error).
    r   Nr   z`usage: hermes kanban <action> [options]
Run 'hermes kanban --help' for the full list of actions.filer   r   boardHERMES_KANBAN_BOARDFr   Nonec                 v    sd S  "t           j                            dd            d S  t           j        d<   d S )Nr  )r\   environpop)prev_board_envrestore_board_envs   r   _restore_board_envz*kanban_command.<locals>._restore_board_envm  sF      	F!JNN0$777770>BJ,---r   kanban:    zkanban: --board requires a slugzkanban: board = does not exist. Create it with `hermes kanban boards create `.   Tz'kanban: could not initialize database: r   r   r   rE   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   zkanban: unknown action )r   r   )6rM   
print_helpprintsysstderr_dispatch_boardsr\   r"  r,   r   _normalize_board_slug
ValueErrorDEFAULT_BOARDboard_existsinit_dbrw   	_cmd_init_cmd_create
_cmd_swarm	_cmd_list	_cmd_show_cmd_assign_cmd_reclaim_cmd_reassign_cmd_diagnostics	_cmd_link_cmd_unlink
_cmd_claim_cmd_comment_cmd_complete	_cmd_edit
_cmd_block_cmd_schedule_cmd_unblock_cmd_promote_cmd_archive	_cmd_tail_cmd_dispatch_cmd_daemon
_cmd_watch
_cmd_stats_cmd_log	_cmd_runs_cmd_heartbeat_cmd_assignees_cmd_notify_subscribe_cmd_notify_list_cmd_notify_unsubscribe_cmd_context_cmd_specify_cmd_decompose_cmd_gcr   RuntimeError)rG   r   parserboard_overrider&  normedexchandlershandlerr$  r%  s            @@r   kanban_commandra  I  s0   
 T?D11F /66KZ   
 q %%% T7D11NZ^^$9::N? ? ? ? ? ? ?  !	-n==FF 	 	 	"S""444411111	  	3#*EEEE1 R%%%bof.E.E%J J J?EJ J JZ   
 1,2
() 

   ===CJOOOOqqqqq
'I'K' 	J' 	I	'
 	I' 	I' 	K' 	L' 	M' 	'' 	$' 	I' 	K' 	J' 	L'  	M!'" 	I#' '$ 	J%'& 	M''( 	L)'* 	L+', 	L-'. 	I/'0 	M1'2 	K3'4 	J5'6 	J7'8 	H9': 	I;'< 	^='> 	^?'@ 	3A'B 	.C'D 	5E' 'F ! $M' ' 'HP ll6""G 222DDDDq774==%A&& 	 %   SZ0000qqq
 	sZ   ,C 
C4C//C40F 
G(F<<G5M N'*(N"N* "N''N* *N6c                     dD ]'} t           j                            |           }|r|c S (	 ddlm}  |            pdS # t
          $ r Y dS w xY w)z4Best-effort author name for an interactive CLI call.)HERMES_PROFILE_NAMEHERMES_PROFILEr   )r	   r   )r\   r"  r,   hermes_cli.profilesr	   rw   )envr_   r	   s      r   _profile_authorrg    s    8  JNN3 	HHH	??????&&((2F2   vvs   > 
AAc                z   t          | dd          pd}|dv rt          |           S |dv rt          |           S |dv rt          |           S |dv rt	          |           S |dv rt          |           S |d	k    rt          |           S |d
k    rt          |           S t          d|t          j
                   dS )at  Handle ``hermes kanban boards <action>``.

    Boards management is deliberately separate from the task-level
    commands: it operates on the filesystem (board directories,
    ``current`` pointer, ``board.json``), not on the per-board SQLite
    DB, so a fresh HERMES_HOME that has never called ``kanban init``
    can still run ``boards create`` / ``boards list``.
    r   NrE   >   r   rE   >   r   r   >   r   r   r   >   r   r   >   r   r   r   r   zkanban boards: unknown action r  r(  )rM   _cmd_boards_list_cmd_boards_create_cmd_boards_rm_cmd_boards_switch_cmd_boards_show_cmd_boards_rename_cmd_boards_set_default_workdirr-  r.  r/  )rG   r   s     r   r0  r0    s     $
.
.
8&C
n%%%
!$'''
(((d###
!$'''
!!!%%%
h!$'''
###.t444	
23
2
2DDDD1r   r   dict[str, int]c                >   	 t          j        |           }|                                si S t          j        |           5 }|                    d                                          }ddd           n# 1 swxY w Y   d |D             S # t          $ r i cY S w xY w)zDReturn ``{status: count}`` for a board. Safe to call on an empty DB.)r  z7SELECT status, COUNT(*) AS n FROM tasks GROUP BY statusNc                F    i | ]}|d          t          |d                   S )r-   n)r   ri   rs     r   
<dictcomp>z&_board_task_counts.<locals>.<dictcomp>	  s(    777Q(S3[[777r   )r   kanban_db_pathexistsconnect_closingexecutefetchallrw   )r   r]   connrowss       r   _board_task_countsr~    s    
 t,,,{{}} 	Id+++ 	t<<I hjj 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 87$7777   			s:   *B B (A6*B 6A::B =A:>B BBc           
        t          t          | dd                    }t          j        |          }t          j                    }|D ]S}|d         |k    |d<   t          |d                   |d<   t          |d                                                   |d<   Tt          | dd          r&t          t          j
        |d	d
                     dS |st          d           dS t          ddddddddd           |D ]}|d         rdnd}|d         pi }d                    d t          |                                          D                       pd}|                    d          pd}|                    d          r|dz  }t          |dd|d         dd|dd|            t                       t          d|            t          |          dk    rt          d           dS ) NallFinclude_archivedr   
is_currentcountstotalr   r(  indentensure_asciir   uD   (no boards — create one with `hermes kanban boards create <slug>`)r   2sr(   SLUG24sNAME28s  COUNTSr   r'   , c              3  *   K   | ]\  }}| d | V  dS =N ri   kr_   s      r   rk   z#_cmd_boards_list.<locals>.<genexpr>#  s0      DDTQjjQjjDDDDDDr   z(empty)r   r   z [archived]Current board: r+  z8Switch boards with `hermes kanban boards switch <slug>`.)ry   rM   r   list_boardsget_current_boardr~  sumvaluesr-  r   dumpsjoinr   itemsr,   rY   )	rG   r  r   r   bmarkerr  
counts_strr   s	            r   ri  ri    s9   GD%7788^-=>>>F"$$G / /V9/,(633(8++--..'

tVU## dj>>>???q TUUUq	R
8
8
8f
8
8
8F
8
8
8
8999 
I 
IL/2s8"IIDDVFLLNN-C-CDDDDD  	 uuV}}"55 	"M!DGGGaiGGGtGGG:GGHHHH	GGG	
%G
%
%&&&
6{{QHIII1r   c                   	 t          j        | j                  }n6# t          $ r)}t	          d| t
          j                   Y d }~dS d }~ww xY w|st	          dt
          j                   dS t          j        |          o|t           j        k    }t          j	        || j
        | j        | j        | j        | j                  }|rdnd}t	          d|d	         d
| d           t	          d|                    dd                      t	          d|d                     t!          | dd          r4t          j        |d	                    t	          d|d	         d           nt	          d|d	          d           dS )Nzkanban boards create: r  r(  z&kanban boards create: slug is required)r   r   r2   colordefault_workdirzalready existscreatedBoard r   r'   .  Display name: r   r     DB path:      db_pathr   Fz  Switched to z#  Use `hermes kanban boards switch z` to make it current.r   )r   r1  r   r2  r-  r.  r/  r4  r3  create_boardr   r   r2   r  r  r,   rM   set_current_board)rG   r]  r^  alreadymetaverbs         r   rj  rj  1  s   )$)44   ,s,,3:>>>>qqqqq  6SZHHHHqof%%D&B4D*DG?Y$Yj,  D  '5ID	
+4<
+
+D
+
+
+,,,	
3TXXfb11
3
3444	
.T)_
.
.///tXu%% Y
T&\***0tF|0001111WDLWWWXXX1    
AA

Ac                   t          | dd          pt          | dd          dk    }	 t          j        | j        |           }n6# t          $ r)}t          d| t          j                   Y d }~dS d }~ww xY w|d	         d
k    r1t          d|d         d|d                     t          d           nt          d|d         d           dS )Nr   Fr   r   )r   zkanban boards rm: r  r+  r   r   r  r   u    archived → new_pathzERecover by moving the directory back to <root>/kanban/boards/<slug>/.z	 deleted.r   )rM   r   remove_boardr   r2  r-  r.  r/  )rG   force_deleteresr^  s       r   rk  rk  O  s   
 4511cWT?TV5W5W[c5cLodi\1ABBB   (3((sz::::qqqqq 8}
""Es6{EEC
OEEFFF . 	/ 	/ 	/ 	/ 	/s6{///0001s   A 
A8A33A8c                   	 t          j        | j                  }n6# t          $ r)}t	          d| t
          j                   Y d }~dS d }~ww xY w|st	          dt
          j                   dS t          j        |          s$t	          d|d| dt
          j                   dS t          j        |           t	          d	|d
           dS )Nzkanban boards switch: r  r(  z&kanban boards switch: slug is requiredzkanban boards switch: board r)  r*  r+  zActive board is now r  r   )	r   r1  r   r2  r-  r.  r/  r4  r  )rG   r]  r^  s      r   rl  rl  c  s   )$)44   ,s,,3:>>>>qqqqq  6SZHHHHq?6"" F6 F F;AF F F	
 	
 	
 	

 q   	
,
,
,
,---1r  c                b   t          j                    }t          j        |          }t          |          }t	          |                                          }t          d|            t          d|                    dd                      |                    d          rt          d|d                     t          d|d                     t          d	| d
|rBdd                    d t          |
                                          D                        dndz              dS )Nr  r  r   r   r   z  Description:  r  r  z  Tasks:        z total (r  c              3  *   K   | ]\  }}| d | V  dS r  r  r  s      r   rk   z#_cmd_boards_show.<locals>.<genexpr>  s0      JJ41aqJJ1JJJJJJJJr   r   r   )r   r  read_board_metadatar~  r  r  r-  r,   r  r   r  )rG   r   r  r  r  s        r   rm  rm  x  s<   "$$G!'**D((F  E	
%G
%
%&&&	
3TXXfb11
3
3444xx 86m!466777	
.T)_
.
.///	
*U
*
*
*M$))JJ6&,,..3I3IJJJJJMMMM  ! ! ! 1r   c                   	 t          j        | j                  }n6# t          $ r)}t	          d| t
          j                   Y d }~dS d }~ww xY w|rt          j        |          s&t	          d| j        dt
          j                   dS t          j        || j	                  }t	          d|d	|d
         d           dS )Nzkanban boards rename: r  r(  zkanban boards rename: board  does not existr+  )r   r  z renamed to r   r  r   )
r   r1  r   r2  r-  r.  r/  r4  write_board_metadatar   )rG   r]  r^  r  s       r   rn  rn    s    )$)44   ,s,,3:>>>>qqqqq  00 ITYIII:	 	 	 	q"6	:::D	
:6
:
:f
:
:
:;;;1r  c                   	 t          j        | j                  }n6# t          $ r)}t	          d| t
          j                   Y d }~dS d }~ww xY w|rt          j        |          s&t	          d| j        dt
          j                   dS t          j        || j	                  }|
                    d          }|rt	          d	|d
|d           nt	          d	|d           dS )Nz#kanban boards set-default-workdir: r  r(  z)kanban boards set-default-workdir: board r  r+  )r  r  r  z default workdir set to r  z default workdir cleared.r   )r   r1  r   r2  r-  r.  r/  r4  r  r]   r,   )rG   r]  r^  r  new_vals        r   ro  ro    s&   )$)44   9C99
KKKKqqqqq  00 V$)VVV:	 	 	 	q"649EEEDhh())G <EvEEEEEFFFF:v:::;;;1r  c                   | | dk    rdS t          |                                                                           }	 t          |          S # t          $ r Y nw xY wddddd}|rf|d         |v r\	 t          |dd                   }n%# t          $ r}t	          d	|           |d}~ww xY wt          |||d                  z            S t	          d	| d
          )u   Parse ``30s`` / ``5m`` / ``2h`` / ``1d`` or a raw integer → seconds.

    Returns None for empty input. Raises ValueError on malformed input so
    the CLI can surface a usage error cleanly.
    Nr   r+  <     iQ )smhdzmalformed duration z( (expected 30s, 5m, 2h, 1d, or a number))r   rW   lowerr   r2  r   )valr  unitsrs  r^  s        r   _parse_durationr    s    {cRiitC  A1vv    "4e44E %QrUe^^	EafAA 	E 	E 	E:3::;;D	E1uQrU|#$$$
Z3ZZZ
[
[[s)   A 
AA2B
 

B,B''B,c                   t          j                    }t          d|            	 t                      pd}t	          |          }t          |d          }|r@|                    dg           }|r(t          d| dd                    |                      n# t          $ r Y nw xY wt                       	 t          j	                    }n# t          $ r g }Y nw xY w|r8t          d	t          |           d
           |D ]}t          d|            nt          d           t          d           t                       t          d           t          d           t                       t          d           dS )NzKanban DB initialized at r   T)quietcopiedzSeeded skill(s) into profile : r  zDiscovered z7 profile(s) on disk; any of these can be an --assignee:r(   z,No profiles found under ~/.hermes/profiles/.z@Create one with `hermes -p <name> setup` before assigning tasks.zCNext step: start the gateway so ready tasks actually get picked up.z  hermes gateway startzThe gateway hosts an embedded dispatcher that ticks every 60 seconds
by default (config: kanban.dispatch_interval_seconds). Without a
running gateway, tasks stay in 'ready' forever.r   )r   r5  r-  r	   r
   r   r,   r  rw   list_profiles_on_diskrY   )rG   r]   profile_nameprofile_dirr?   r  profilesr   s           r   r6  r6    s   :<<D	
,d
,
,---	.00=I%l33$[=== 	[ZZ"--F [YlYYdiiPVFWFWYYZZZ    
GGG+--    R #CMM # # # 	$ 	$ 	$ 	 	D+t++	 	<===PQQQ	GGG	
OPPP	
"###	GGG		:  
 1s$   A2B 
B'&B'9C CCc           
     V   t          j                    5 }t          j        || j        t	          | dd           t          | j                            }d d d            n# 1 swxY w Y   |s&t          d| j         dt          j                   dS t          d| j                    dS )	Nnote)r  expected_run_idzcannot heartbeat z (not running?)r  r+  zHeartbeat recorded for r   )	r   ry  heartbeat_workerr   rM   _worker_run_id_forr-  r.  r/  rG   r|  oks      r   rQ  rQ    s    				 
 Lvt,,.t|<<	
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
  ?$,???cjQQQQq	
2DL
2
23331s   ?AA#&A#c                :   t          j                    5 }t          j        |          }d d d            n# 1 swxY w Y   t          | dd          r&t	          t          j        |dd                     dS |st	          d           dS t	          ddd	d
dd           |D ]w}|d         rdnd}|d         pi }d                    d t          |	                                          D                       pd}t	          |d         dd	|dd	|            xdS )Nr   Fr(  r  r   uA   (no assignees — create a profile with `hermes -p <name> setup`)r  r*   r(   zON DISKr)   r  on_diskyesnor  r  c              3  *   K   | ]\  }}| d | V  dS r  r  r  s      r   rk   z!_cmd_assignees.<locals>.<genexpr>  0      LLTQjjQjjLLLLLLr   z(idle)r   )
r   ry  known_assigneesrM   r-  r   r  r  r   r  )rG   r|  dataentryr  r  	count_strs          r   rR  rR    s   				 (!$''( ( ( ( ( ( ( ( ( ( ( ( ( ( (tVU## djae<<<===q QRRRq	V
1
1
19
1
1
1
1222 A A +5%%x&BIILLVFLLNN5K5KLLLLLXPX	v???g???I??@@@@1   599c                   	 t          | j                  \  }}t          t          | dd                     }n;# t          j        $ r)}t          d| t          j                   Y d }~dS d }~ww xY w|r#|dk    rt          dt          j                   dS 	 t          t          | dd                     }n6# t          $ r)}t          d| t          j                   Y d }~dS d }~ww xY wt          | d	d           }|'|d
k     r!t          d| dt          j                   dS t          j                    5 }t          j        |fi d| j        d| j        d| j        d| j        pt%                      d|d|d|d| j        d| j        dt+          | j        pd          dt/          t          | dd                    dt          | dd           d|dt          | dd           pd d	|dt          | dd          }t          j        ||          }	d d d            n# 1 swxY w Y   t          | dd          r2t          t3          j        t7          |	          dd                      njt          d!| d"|	j         d#|	j        pd$ d%           |	j        d&k    r:|	j        r3t;                      \  }
}|
s |rt          d'| t          j                   d(S ))Nrm   r'  r  r(  rU   z8kanban: --branch is only valid with --workspace worktreemax_runtimezkanban: --max-runtime: rA   r+  z(kanban: --max-retries must be >= 1 (got z&); use 1 to trip on the first failure.r1   r6   r.   r;   r8   r9   r:   r/   r7   parentsr  triageFidempotency_keymax_runtime_secondsr@   initial_statusr   r   r  zCreated z  (z, assignee=re   r   r   u   
⚠  r   )rb   	workspacern   rM   rZ   r[   r-  r.  r/  r  r2  r   ry  create_taskr1   r6   r.   r;   rg  r/   r7   tupleparentry   get_taskr   r  rF   r-   r}   )rG   ws_kindws_pathr:   r^  r  rA   r|  r   taskr   messages               r   r7  r7    s   0@@(x)F)FGG%   SZ0000qqqqq  w*,,HszZZZZq%gdM4&H&HII   ---CJ????qqqqq $t44K;??2{ 2 2 2	
 	
 	
 	

 q				 *.
 
 
**
 
 ]]	

 ;/*;*;
 #7
 #7
 $
 ;;
 ]]
 $++,,,
 h66777
 $D*;TBBB
 !,
 44008D
  $!
" #4)99EEE#
& {4)))* * * * * * * * * * * * * * ** tVU## <djt,,QUKKKLLLLTTTT[TTT]=QcTTTUUU ;'!!dm!9;;GW <w <)))
;;;;1s@   58 A0A++A0B8 8
C+C&&C+;C!H((H,/H,c                N   	 d | j         pg D             }n6# t          $ r)}t          d| t          j                   Y d }~dS d }~ww xY w|st          dt          j                   dS t          j                    5 }t          j        || j	        || j
        | j        | j        | j        pt                      | j        t!          | dd           	  	        }d d d            n# 1 swxY w Y   t!          | dd	          r7t          t#          j        |                                dd	
                     not          d|j                    t          dd                    |j                  z              t          d|j                    t          d|j                    dS )Nc                6    g | ]}t          j        |          S r  )ksparse_worker_arg)ri   raws     r   
<listcomp>z_cmd_swarm.<locals>.<listcomp>Z  s#    KKK2&s++KKKr   zkanban swarm: r  r(  z/kanban swarm: at least one --worker is requiredr  )r   workersverifier_assigneesynthesizer_assigneer/   r;   r7   r  r   Fr  zSwarm root: z	Workers: r  z
Verifier: zSynthesizer: r   )workerr2  r-  r.  r/  r   ry  r  create_swarmr   verifiersynthesizerr/   r;   rg  r7   rM   r   r  as_dictroot_idr  
worker_idsverifier_idsynthesizer_id)rG   r  r^  r|  r  s        r   r8  r8  X  s   KK8IrKKK   $s$$3:6666qqqqq  ?cjQQQQq				 
/"m!%!1;;/*;*;]#D*;TBB

 

 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 tVU## 8dj**15IIIJJJJ.W_..///kDIIg&8999:::07.001116g4667771s'    
A	AA	>AC##C'*C'c                B   | j         }| j        r|st                      }t          j                    5 }t          j        |           t          j        ||| j        | j        | j	        | j
        t          | dd           | j        | j        	  	        }d d d            n# 1 swxY w Y   t          | dd          r0t          t          j        d |D             dd                     dS 	 t          j        d	          }n# t$          $ r g }Y nw xY wt'          |          d
k    rFt          j                    }t'          |          d
z
  }t          d| d| d|d
k    rdnd d           |st          d           dS |D ]}t          t+          |                     dS )Nsort)r.   r-   r/   rB   r  order_byrC   rD   r   Fc                ,    g | ]}t          |          S r  )rF   )ri   r    s     r   r  z_cmd_list.<locals>.<listcomp>  s     :::q-**:::r   r(  r  r   r  r+  zBoard: r  z other boardr  r   u"    — `hermes kanban boards list`)
z(no matching tasks))r.   minerg  r   ry  recompute_ready
list_tasksr-   r/   sessionr   rM   rC   rD   r-  r   r  r  rw   rY   r  r3   )rG   r.   r|  tasks
all_boardsr   other_countr    s           r   r9  r9  w  s5   }Hy % %"$$				 
 	4   ;;|!]T6400!%!:!2

 

 

	
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 tVU## dj::E:::1SXYYYZZZq^U;;;

   



:&((*oo).g . .. .0;q0@0@b. . .	
 	
 	

  #$$$q ! !nQ    1s$   ABB!$B!*D   DDc                   t          |           }|t          dt          j                   dS t	          j                    5 }t	          j        || j                  }|s1t          d| j         t          j                   	 d d d            dS t	          j        || j                  }t	          j	        || j                  }t	          j
        || j                  }t	          j        || j                  }t	          j        || j        fi |}t	          j        || j                  }	d d d            n# 1 swxY w Y   t          | dd          r[t          |          |	||d |D             d	 |D             d
 |D             d}
t          t!          j        |
dd                     dS t          d|j         d|j                    t          d|j                    t          d|j        pd            |j        rt          d|j                    t          d|j         |j        r
d|j         ndz              |j        rt          d|j                    |j        r*t          dd                    |j                              |j        rt          d|j                    |j        t          d|j         d           n	 ddlm}  |            }|                     di           pi                      d          }n# tB          $ r d }Y nw xY w|>tE          |          t          j#        k    r!t          dtE          |           d            nt          dt          j#         d!           t          d"tI          |j%                   d#|j&        pd            dd$l'm(} |)                    |||          }|rFd%d&d'd(}t          d)tU          |           d*           |D ]}t          d+|                     |j+        d,           d-|j+         d.|j                    |j,        rg }|j,        -                                D ]l\  }}t]          |t^                    r8|0                    | d/d0                    d1 |D                                   R|0                    | d/|            m|r%t          d2d3                    |                      |j1        D ] }|j2        rt          d4|j3                    !|j4        r$t          d5tI          |j4                              |j5        r$t          d6tI          |j5                              |r%t          d7d                    |                      |r%t          d8d                    |                      |j6        r1t                       t          d9           t          |j6                   |j7        r2t                       t          d:           t          |j7                   n.|	r,t                       t          d;           t          |	           |rgt                       t          d<tU          |           d*           |D ]6}t          d=tI          |j%                   d.|j8         d|j6                    7|rt                       t          d>tU          |           d*           |d?d          D ]Z}|j9        r
d@|j9         nd}|j:        rdA|j:         dBnd}t          d=tI          |j%                   dB| d@|j;         |            [|r,t                       t          dCtU          |           d*           |D ]}|j<        rt{          d|j<        |j4        z
            nd }|| dDndE}|j>        p|j        pdE}t          dF|j        dGd@|dHdI|j?        pd dJ| dJtI          |j4                   
           |j@        r7t          dK|j@        A                                d         d dL                     |jB        r7t          dM|jB        A                                d         d dL                     dS )NNzBkanban show: pass both --state-type and --state-name, or omit bothr  r(  no such task: r+  r   Fc                8    g | ]}|j         |j        |j        d S )authorr6   r<   r  )ri   cs     r   r  z_cmd_show.<locals>.<listcomp>  s8        8QV1<PP  r   c                D    g | ]}|j         |j        |j        |j        d S )ra   payloadr<   run_idr  )ri   es     r   r  z_cmd_show.<locals>.<listcomp>  sE         F y"#,h	   r   c                    g | ]G}|j         |j        |j        |j        |j        |j        |j        |j        |j        |j	        |j
        d HS )r0   r   step_keyr-   r   summaryr   metadata
worker_pidr=   ended_atr  rt  s     r   r  z_cmd_show.<locals>.<listcomp>  sh         $ y !
h y yW !
"#,"#, !
   r   )r  latest_summaryr  childrencommentseventsr   r  r   zTask r  z  status:    z  assignee:  re   z  tenant:    z  workspace: z @ r   z  branch:    z  skills:    r  z  model:     z  max-retries: z (task)rr   rt   failure_limitz (config kanban.failure_limit)z
 (default)z  created:   z by kanban_diagnostics   ⚠!!!!!r   z
  Diagnostics (z):    r#   r%   ] r  ,c              3  4   K   | ]}t          |          V  d S rg   r   ri   xs     r   rk   z_cmd_show.<locals>.<genexpr>  (      3F3FqCFF3F3F3F3F3F3Fr          data:  |           → z  started:   z  completed: z  parents:   z  children:  zBody:zResult:zLatest summary:z
Comments (z  [zEvents (ir'   z [run r&   zRuns (r  activez  #z<3z<12z @r(   u           →    z
        ! )CrP   r-  r.  r/  r   ry  r  r   list_commentslist_events
parent_ids	child_ids	list_runsr$  rM   rF   r   r  r0   r1   r-   r.   r/   r8   r9   r:   r@   r  model_overriderA   rx   rs   r,   rw   r   r   r   r<   r;   
hermes_clir*  compute_task_diagnosticsrY   severityr  r  
isinstancerE   r   actions	suggestedlabelr=   r>   r6   r?   r  r  r  ra   r#  maxr   r   r   
splitlinesr   )rG   rskr|  r  r&  r'  r  r%  r   r$  r  rs   r{   cfg_valkddiags
sev_markerr  bitsr  r_   ar  r  plrun_tagru  elapsedelr   s                                 r   r:  r:    s@
   
D
!
!C
{P	
 	
 	
 	
 q				 ?{4.. 	14<11
CCCC	? ? ? ? ? ? ? ?
 #D$,77dl33-dl33<dl33|D$,66#66
 *4>>? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  tVU## %!$'',  !           %"
 "
F 	dj???@@@q	
)$'
)
)TZ
)
)***	
'$+
'
'(((	
0$-.3
0
0111{ -+dk++,,,	
/$-
/
/*.*=E&$&&&2G H H H 20d.00111{ 86dii4466777 53d133444
 #9 0999::::	555555+--Cwwx,,277HHGG 	 	 	GGG	3w<<23K#K#KPCLLPPPQQQQHB$<HHHIII	
P'$/22
P
P8N3
P
PQQQ
 433333''fd;;E 3!&5II
0#e**000111 	3 	3AS
C88SSAJSS!'SSTTTv >FLLNN 0 0DAq!!T** 0q$H$H3883F3FA3F3F3F+F+F$H$HIIIIqJJ1JJ//// ><%**T*:*:<<=== Y 3 3; 31112223  :8gdo6688999 <:gd&788::;;; 42dii0022333 53dii1133444y gdi{ 
idk	  	   n G,3x==,,,--- 	G 	GAE--EEEEQVEEFFFF H(V((())) 	H 	HA$%I5QY2B./h>*qx****BGF--FFFF!&F"FFGGGG D$s4yy$$$%%% 	D 	DA */s1aj1<7888*. ")"5G8Bi7187xG -K - -'K - -1Ac - -R - -Q\**- - . . .y HFQY%9%9%;%;A%>tt%DFFGGGw DB17#5#5#7#7#:4C4#@BBCCC1s,   AD6BD66D:=D:;L LLc                `   | j                                         dv rd n| j         }t          j                    5 }t          j        || j        |          }d d d            n# 1 swxY w Y   |s%t          d| j         t          j                   dS t          d| j         d|pd            dS )	N>   re   nonenullr  r  r+  z	Assigned  to r$   r   )	r   r  r   ry  assign_taskr   r-  r.  r/  rG   r   r|  r  s       r   r;  r;  P  s    l((**.CCCddG				 9^D$,889 9 9 9 9 9 9 9 9 9 9 9 9 9 9 -t|--CJ????q	
Cdl
C
C(A>
C
CDDD1s   A  A$'A$c           
     0   t          j                    5 }t          j        || j        t	          | dd                     }d d d            n# 1 swxY w Y   |s&t          d| j         dt          j                   dS t          d| j                    dS )	Nr   )r   zcannot reclaim z (not running or unknown id)r  r+  z
Reclaimed r   )r   ry  reclaim_taskr   rM   r-  r.  r/  r  s      r   r<  r<  [  s    				 
_$,4400
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 

  HdlHHH	
 	
 	
 	
 q	
%t|
%
%&&&1s   ,AAAc                   | j                                         dv rd n| j         }t          j                    5 }t          j        || j        |t          t          | dd                    t          | dd                     }d d d            n# 1 swxY w Y   |s&t          d| j         dt          j
                   d	S t          d
| j         d|pd t          | dd          rdndz              dS )N>   re   rV  rW  r   Fr   )reclaim_firstr   zcannot reassign uC    (unknown id, or still running — pass --reclaim to release first)r  r+  zReassigned rX  r$   z (claim reclaimed)r   r   )r   r  r   ry  reassign_taskr   ry   rM   r-  r.  r/  rZ  s       r   r=  r=  k  st   l((**.CCCddG				 
$,wtY>>??4400
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
  Rt| R R R	
 	
 	
 	

 q		'dl 	' 	'$n	' 	'#*4E#B#BJ	L  
 1s   A
BBBc                   ddl m ddlm}                      |                      }t          j                    5 }t          | dd          rt          j        || j	                  }|1t          d| j	         t          j                   	 ddd           dS | j	                            |t          j        || j	                  t          j        || j	                  |	          i}nt!          |                    d
                                                    }d |D             }|si }nGd                    dgt)          |          z            }d |D             }	|                    d| dt+          |                    D ]1}
|	                    |
d         g                               |
           2d |D             }|                    d| dt+          |                    D ]1}
|                    |
d         g                               |
           2i }|D ]R}|d         }                    ||	                    |g           |                    |g           |	          }|r|||<   St          | dd          rDt!          |                                          D ]"}fd||         D             }|r|||<   ||= #i |rd                    dgt)          |          z            }|                    d| dt+          |                                                    D ]#}|d         |d         |d         d|d         <   $ddd           n# 1 swxY w Y   t          | dd          rFfd|                                D             }t          t7          j        |d d!                     dS |st          d"           dS d#d$d%d&}t;          d' |                                D                       }t          | d(t)          |           d)           |                                D ]\  }}                    |i           }|                    d          pd*}|                    d          pd}|                    d          pd+}t          d,| d,|d-d.|d/d,|            |D ]$}t          d0|                    |j        d           d1|j         d2|j          d3|j!                    |j"        rg }|j"                                        D ]l\  }}tG          |t                     r8|                    | d4d                    d5 |D                                   R|                    | d4|            m|r%t          d6d7                    |                      |j$        D ] }|j%        rt          d8|j&                    !&t                       dS )9zList active diagnostics on the board. Wraps the same rule engine
    the dashboard uses, so CLI output matches what the UI shows.
    r   r)  rr   r  Nr  r  r+  )configz.SELECT * FROM tasks WHERE status != 'archived'c                    g | ]
}|d          S )r0   r  rt  s     r   r  z$_cmd_diagnostics.<locals>.<listcomp>  s    )))q1T7)))r   r0  r#   c                    i | ]}|g S r  r  ri   is     r   rv  z$_cmd_diagnostics.<locals>.<dictcomp>  s    ,,,1B,,,r   z,SELECT * FROM task_events WHERE task_id IN (z) ORDER BY idr   c                    i | ]}|g S r  r  rd  s     r   rv  z$_cmd_diagnostics.<locals>.<dictcomp>  s    ---A!R---r   z*SELECT * FROM task_runs WHERE task_id IN (r0   rC  c                    g | ]?}j                             |j                  j                                       k    =|@S r  )SEVERITY_ORDERindexrC  )ri   r  rL  sevs     r   r  z$_cmd_diagnostics.<locals>.<listcomp>  sK    }}}a9J9P9PQRQ[9\9\`b`q`w`wx{`|`|9|9|9|9|9|r   z;SELECT id, title, status, assignee FROM tasks WHERE id IN (r   r1   r-   r.   )r1   r-   r.   r   Fc                f    g | ]-\  }}d |i                     |i           dd |D             i.S )r   r   c                6    g | ]}|                                 S r  )to_dict)ri   r  s     r   r  z/_cmd_diagnostics.<locals>.<listcomp>.<listcomp>  s     888		888r   )r,   )ri   tiddlr  s      r   r  z$_cmd_diagnostics.<locals>.<listcomp>  sl     
 
 
 R	 3((3## 88R888 
 
 
r   r(  r  z$No active diagnostics on this board.r+  r,  r-  r   c              3  4   K   | ]}t          |          V  d S rg   )rY   )ri   ro  s     r   rk   z#_cmd_diagnostics.<locals>.<genexpr>  s(      99BB999999r   z active diagnostic(s) across z
 task(s):
z
(untitled)r$   r(   r)   z  @18sr.  r%   r/  r  r  c              3  4   K   | ]}t          |          V  d S rg   r2  r3  s     r   rk   z#_cmd_diagnostics.<locals>.<genexpr>  r5  r   r6  r7  r8  )'rA  r*  rx   rs   config_from_runtime_configr   ry  rM   r  r  r-  r.  r/  rB  r<  r?  rE   rz  r{  r  rY   r  
setdefaultr   r,   r   r  r   r  r  r  rC  ra   r1   r  rD  rE  rF  rG  )rG   rs   diag_configr|  r  diags_by_taskr}  idsplaceholdersev_byrowrun_byru  rn  ro  keptout_jsonrN  r  r  r1   r-   r.   r  rO  r  r_   rP  rL  r  rj  s                               @@@r   r>  r>    s    433333------//>>K				 F4&& -	0;tTY//D|2ty22DDDDF F F F F F F F 	266N433Lty11&	 7  MM @ hjj D *)D)))C 0 ""xxC(899,,,,,<<^<^^^#JJ  E EC $$S^R88??DDDD-----<<\\\\#JJ  F FC %%c)nb99@@EEEE " 	0 	0AD'C44		#r**

3++*	 5  B  0-/c* dJ-- 	+M..0011 + +}}}}}=#5}}} +)-M#&&%c** !# 		88SEC,>,>$>??L\\]l]]]m((**++   
 wZ1X; !*! !QtWGF F F F F F F F F F F F F F FP tVU## 

 
 
 
 )..00
 
 
 	dj!%@@@AAAq 4555q #TuEEJ99-"6"6"8"899999E	 	+ 	+}	+ 	+ 	+   !&&((  RHHS"g.,x'C55$$6?3??&????????@@@ 	3 	3A]
C88]]AJ]]!&]]TUT[]]^^^v 	>FLLNN 0 0DAq!!T** 0q$H$H3883F3FA3F3F3F+F+F$H$HIIIIqJJ1JJ//// ><%**T*:*:<<===Y 3 3; 31112223 	1s    AM(J=M((M,/M,c                    t          j                    5 }t          j        || j        | j                   d d d            n# 1 swxY w Y   t          d| j         d| j                    dS )NzLinked  -> r   )r   ry  
link_tasksr   r   r-  rG   r|  s     r   r?  r?    s    				 ;
dDNDM:::; ; ; ; ; ; ; ; ; ; ; ; ; ; ;	
7DN
7
7
7
78881   !AAAc                8   t          j                    5 }t          j        || j        | j                  }d d d            n# 1 swxY w Y   |s-t          d| j         d| j         t          j                   dS t          d| j         d| j                    dS )NzNo such link: r  r  r+  z	Unlinked r   )r   ry  unlink_tasksr   r   r-  r.  r/  r  s      r   r@  r@    s    				 B_T4>4=AAB B B B B B B B B B B B B B B Bt~BB4=BBTTTTq	
9dn
9
9$-
9
9:::1r  c           	        t          j                    5 }t          j        || j        | j                  }|t          j        || j                  }|1t          d| j         t          j                   	 d d d            dS t          d| j         d|j	         d|j
        pd t          j                   	 d d d            dS t          j        |          }t          j        ||j        t          |                     d d d            n# 1 swxY w Y   t          d	|j                    t          d
|            dS )N)ttl_secondsr  r  r+  zcannot claim z	: status=z lock=z(none)zClaimed zWorkspace: r   )r   ry  
claim_taskr   ttlr  r-  r.  r/  r-   
claim_lockresolve_workspaceset_workspace_pathr0   r   )rG   r|  r  existingr  s        r   rA  rA    s   				 =}T4<TXFFF<{466H5t|55CJGGGG= = = = = = = = : : :x : : +7x: :Z   
 = = = = = = = = (..	
dDGS^^<<<= = = = = = = = = = = = = = =  

TW

	
#	
#
#$$$1s   A$D6D<DDDc           	     l   d                     | j                                                  }| j        | j        dk     rt	          dt
          j                   dS t          |          | j        k    rMd| j         d}|d t          d| j        t          |          z
                     	                                |z   }| j
        pt                      }t          j                    5 }t          j        || j        ||           d d d            n# 1 swxY w Y   t	          d	| j                    dS )
Nr'   r+  z"kanban: --max-len must be positiver  r(  z

[trimmed to z chars by --max-len]r   zComment added to )r  r   rW   max_lenr-  r.  r/  rY   rH  rstripr  rg  r   ry  add_commentr   )rG   r6   suffixr  r|  s        r   rB  rB  ,  sW   88DI$$&&D|<!6SZHHHH1t99t|##JJJJF<#aF!;<<<=DDFFOD[-O--F				 9
tT\648889 9 9 9 9 9 9 9 9 9 9 9 9 9 9	
,dl
,
,---1s   )DDDr   c                    t           j                            d          | k    rd S t           j                            d          }|sd S 	 t          |          S # t          $ r Y d S w xY w)NHERMES_KANBAN_TASKHERMES_KANBAN_RUN_ID)r\   r"  r,   r   r2  )r   r  s     r   r  r  <  st    	z~~*++w66t
*../
0
0C t3xx   tts   
A 
A'&A'c                p   t          | j        pg           }|st          dt          j                   dS t          | dd          }t          | dd          }t          |          dk    r!|s|rt          dt          j                   dS d}|r|	 t          j        |          }t          |t                    st          d	          nB# t          t          j        f$ r)}t          d
| t          j                   Y d}~dS d}~ww xY wg }t          j                    5 }|D ]u}t          j        ||| j        ||t#          |                    s5|                    |           t          d| dt          j                   ct          d|            v	 ddd           n# 1 swxY w Y   |sdndS )z<Mark one or more tasks done. Supports a single id or a list. at least one task_id is requiredr  r+  r   Nr!  zkanban: --summary / --metadata are per-task and can't be used with multiple ids (would apply the same handoff to every task). Complete tasks one at a time, or drop the flags for the bulk close.r(  must be a JSON objectkanban: --metadata: )r?   r   r!  r  zcannot complete z (unknown id or terminal state)z
Completed r   )rE   r   r-  r.  r/  rM   rY   r   loadsrD  dictr2  JSONDecodeErrorr   ry  complete_taskr?   r  r   )	rG   rw  r   raw_metar!  r^  failedr|  rn  s	            r   rC  rC  H  sN   
t}"
#
#C 0szBBBBqdIt,,GtZ..H 3xx!|||H|R 		
 	
 	
 	
 qH 	z(++Hh-- : !8999:D01 	 	 	...SZ@@@@11111	 F				 * 	* 	*C#c{! 23 7 7   
* c"""MMMMTWT^_____(3(())))	** * * * * * * * * * * * * * * !11!s+   8C
 
D	 DD	!A9F''F+.F+c                v   t          | dd           }d }|r|	 t          j        |          }t          |t                    st          d          nB# t
          t          j        f$ r)}t          d| t          j	                   Y d }~dS d }~ww xY wt          j                    5 }t          j        || j        | j        t          | dd           |          s2t          d| j         d	t          j	                   	 d d d            d
S 	 d d d            n# 1 swxY w Y   t          d| j                    dS )Nr!  r  r  r  r(  r   )r?   r   r!  zcannot edit z! (unknown id or task is not done)r+  zEdited r   )rM   r   r  rD  r  r2  r  r-  r.  r/  r   ry  edit_completed_task_resultr   r?   )rG   r  r!  r^  r|  s        r   rD  rD  u  s   tZ..HH 	z(++Hh-- : !8999:D01 	 	 	...SZ@@@@11111	 
			 ,L;D)T22
 
 
 	 Nt|NNNZ           	               

"DL
"
"###1s*   8A B&B

B%ADDDc           
     n   | j         r,d                    | j                                                   nd }t                      }| j        gt          t          | dd           pg           z   }g }t          j                    5 }|D ]}|rt          j	        |||d|            t          j
        |||t          |                    s4|                    |           t          d| t          j                   wt          d| |rd| nd	z              	 d d d            n# 1 swxY w Y   |sd
ndS )Nr'   rw  z	BLOCKED: r   r  zcannot block r  zBlocked r  r   r   r+  )r   r  rW   rg  r   rE   rM   r   ry  r  
block_taskr  r   r-  r.  r/  rG   r   r  rw  r  r|  rn  s          r   rE  rE    s   .2kCSXXdk""((***tFF<.4eT : : @bAA
ACF				 L 	L 	LC HtS&2Ff2F2FGGG= 23 7 7	   	L c"""+c++#*=====&&&6*I-v---rJKKKK	LL L L L L L L L L L L L L L L !11!   BD&&D*-D*c           
     n   | j         r,d                    | j                                                   nd }t                      }| j        gt          t          | dd           pg           z   }g }t          j                    5 }|D ]}|rt          j	        |||d|            t          j
        |||t          |                    s4|                    |           t          d| t          j                   wt          d| |rd| nd	z              	 d d d            n# 1 swxY w Y   |sd
ndS )Nr'   rw  zSCHEDULED: r  zcannot schedule r  z
Scheduled r  r   r   r+  )r   r  rW   rg  r   rE   rM   r   ry  r  schedule_taskr  r   r-  r.  r/  r  s          r   rF  rF    s   .2kCSXXdk""((***tFF<.4eT : : @bAA
ACF				 N 	N 	NC JtS&2H2H2HIII# 23 7 7	   	N c"""...SZ@@@@@(3((V,KMMMMLMMMM	NN N N N N N N N N N N N N N N !11!r  c           	     X   t          | j        pg           }|st          dt          j                   dS t          | dd           }||                                pd }|rt                      nd }g }t          j	                    5 }|D ]}|rt          j
        |||d|            t          j        ||          s5|                    |           t          d| dt          j                   ht          d| |rd	| nd
z              	 d d d            n# 1 swxY w Y   |sdndS )Nr  r  r+  r   z	UNBLOCK: zcannot unblock z (not blocked/scheduled?)z
Unblocked r  r   r   )rE   r   r-  r.  r/  rM   rW   rg  r   ry  r  unblock_taskr   )rG   rw  r   r  r  r|  rn  s          r   rG  rG    s   
t}"
#
#C 0szBBBBqT8T**F'4"(2_dFF				 N 	N 	NC HtS&2Ff2F2FGGG?4-- Nc"""FFFFSZXXXXX(3((V,KMMMMLMMMM	NN N N N N N N N N N N N N N N !11!s   BDD"Dc                   | j         r,d                    | j                                                   nd }t                      }t	          | dd          }t          t	          | dd           pg           }g }t                      }| j        g|D ]0}||vr*|                    |           |	                    |           1g }t          j                    5 }	|D ]}t          j        |	|||t          | j                  t          | j                            \  }
}|                    ||
t          | j                  t          | j                  ||d           	 d d d            n# 1 swxY w Y   d |D             }|rGt!          |          dk    r|d	         n|}t#          t%          j        |d
d                     |sd	ndS | j        rdnd}| j        rdnd}|D ]`}|d         r)|rd| nd}t#          | d|d          d| |            3t#          d|d          d|d          t(          j                   a|sd	ndS )Nr'   r   Frw  )actorr   forcedry_run)r   promotedr  forcedr   r   c                "    g | ]}|d          
|S )r  r  rt  s     r   r  z _cmd_promote.<locals>.<listcomp>  s!    666A*6a666r   r+  r   r(  r   (dry)r   zWould promotePromotedr  r  r   z	 -> readyzcannot promote r   r  )r   r  rW   rg  rM   rE   setr   r   addr   ry  promote_taskry   r  r  rY   r-  r   r  r.  r/  )rG   r   r  as_json	extra_idsrw  seenrn  resultsr|  r  errr  r  tagrG  ru  r  s                     r   rH  rH    s   .2kCSXXdk""((***tFFdFE**GWT5$//5266ICUUD)y)  d??JJsOOOHHSMMM')G				  	 	Co4:&&T\**  GB NN--tz**      	              & 76666F &(+G(9(9'!**wdj???@@@%qqA%l
*((C#|;OOE S SZ= 	S&,4]&]]]"FUAAQy\AACAAABBBB@AiL@@AgJ@@szRRRRR!11!s   BE))E-0E-c                   t          | j        pg           }t          t          | dd           pg           }|r|rt          dt          j                   dS |s|st          dt          j                   dS g }t          j                    5 }|rs|D ]^}t          j        ||          s5|	                    |           t          d| dt          j                   Lt          d|            _|sd	ndcd d d            S |D ]]}t          j
        ||          s4|	                    |           t          d
| t          j                   Kt          d|            ^	 d d d            n# 1 swxY w Y   |sd	ndS )Nr   z;choose either task_ids to archive or --rm archived task_idsr  r+  r  zcannot delete z (must already be archived)zDeleted r   zcannot archive z	Archived )rE   r   rM   r-  r.  r/  r   ry  delete_archived_taskr   archive_task)rG   rw  r   r  r|  rn  s         r   rI  rI    s*   
t}"
#
#CWT;55;<<I
 y KRUR\]]]]q y 0szBBBBqF				 ) 	*  , ,.tS99 ,MM#&&&K3KKKRUR\]]]]]*S**++++")11) ) ) ) ) ) ) )  	) 	)C?4-- )c"""---CJ?????'#''((((	)) ) ) ) ) ) ) ) ) ) ) ) ) ) ) !11!s   A)E1A E11E58E5c                   d}t          d| j         d           	 	 t          j                    5 }t          j        || j                  }d d d            n# 1 swxY w Y   |D ]W}|j        |k    rJ|j        r
d|j         nd}t          dt          |j                   d|j	         | d	           |j        }Xt          j        t          d
| j                             # t          $ r t          d           Y dS w xY w)Nr   zTailing events for z. Ctrl-C to stop.Tr'   r   [r/  flush皙?

(stopped))r-  r   r   ry  r<  r0   r  r   r<   ra   r   sleeprH  intervalKeyboardInterrupt)rG   last_idr|  r'  r  rQ  s         r   rJ  rJ  "  sc   G	
?
?
?
?@@@	0#%% <dl;;< < < < < < < < < < < < < < < # #4'>>,-I=QY2BCgal33CCqvCrCC4PPPPdGJs3..///	0    mqqs5   C$ AC$ AC$ ABC$ $D Dc                *	   	 ddl m}  |            }t          |t                    r|                    di           ni }|                    d          pd                                pd }d } ||                    d                    } ||                    d                    }t          | d	d           }||n ||                    d
                    }	n'# t          $ r d }d }d }t          | d	d           }	Y nw xY wt          j	                    5 }
t          j
        |
| j        |	|t          | dt          j                  ||          }d d d            n# 1 swxY w Y   t          | dd          r|t          t          j        |j        |j        |j        |j        |j        |j        d |j        D             |j        |j        d |j        D             |j        dd                     dS t          d|j                    t          dt7          |j                              |j        r*t          dd                    |j                              t          dt7          |j                              |j        r*t          dd                    |j                              t          dt7          |j                              |j        r*t          dd                    |j                              t          dt7          |j                              |j        r*t          dd                    |j                              t          d|j                    t          dt7          |j                              |j        D ]-\  }}}| j        rdnd}t          d| d| d |pd! |            .|j        r-t          d"|d#d                    |j                              |j        r*t          d$d                    |j                              |j        r&|j        D ]\  }}}t          d%| d&| d'|            |j        r*t          d(d                    |j                              dS ))Nr   rr   rt   default_assigneer   c                p    | d S 	 t          |           }n# t          t          f$ r Y d S w xY w|dk    r|nd S )Nr+  )r   	TypeErrorr2  )rQ   ivals     r   _coerce_positive_intz+_cmd_dispatch.<locals>._coerce_positive_intB  sW    }t5zzz*   tt19944$.s    ++max_in_progress_per_profilemax_in_progressrH  	max_spawnr(  )r  r  r  r(  r  r  r   Fc                "    g | ]\  }}}|||d S ))r   r.   r  r  )ri   rn  whowss       r   r  z!_cmd_dispatch.<locals>.<listcomp>l  s8       "S#r  SrBB  r   c                "    g | ]\  }}}|||d S ))r   r.   r   r  )ri   rn  r  r   s       r   r  z!_cmd_dispatch.<locals>.<listcomp>r  s8     + + +'S#w  SWEE+ + +r   )	reclaimedcrashed	timed_outstaleauto_blockedr  spawnedskipped_unassignedskipped_nonspawnableskipped_per_profile_cappedauto_assigned_defaultr(  )r  zReclaimed:    zCrashed:      r(   r  zTimed out:    zStale:        zAuto-blocked: zPromoted:     zSpawned:      r  z  - z  ->  z  @ re   z)Auto-assigned to kanban.default_assignee=r  zSkipped (unassigned): z
Deferred (z at per-profile cap, z running): u8   Skipped (non-spawnable assignee — terminal lane, OK): )rx   rs   rD  r  r,   rW   rM   rw   r   ry  dispatch_oncer  r   r-  r   r  r  r  r  r  r  r  r  r  r  r  r  rY   r  )rG   rs   _cfg_kanban_cfgr  r  r  r  cli_maxr  r|  r  rn  r  r  r  r   s                    r   rK  rK  4  s   /111111{}}0:40F0FNdhhx,,,B'OO,>??E2LLNNVRV	/ 	/ 	/ ';&:OO9::'
 '
# /.{?P/Q/QRR $t,,&2GG8L8LOOK((9
 9
		  / / /&*#D%..				/
 
			 	
L+!$9WXX-(C
 
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 tVU## dj{Y, &)k   #&"8$'$<+ ++.+I+ + + &)%>#
 
$ %   	 	 	& q	
*3=
*
*+++	
-3s{++
-
-...
{ -+499S[))++,,,	
/3s}--
/
/000
} /-499S]++--...	
+3sy>>
+
+,,,
y +)499SY''))***	
23s/00
2
2333
 20499S-..00111	
)3<
)
)***	
-3s{++
-
-... ; ;S",.hhB9S9999s9C99::::
  
68H 6 6yy2336 6	
 	
 	
  LJtyy1G'H'HJJKKK
% !$!? 	 	CgPSPPwPP3PP     
5yy1225 5	
 	
 	
 1s$   CC !D D:EE!$E!c           	     H   t          | dd          st          dt          j                   dS t	          j                     t          | dd          }|r	 t          |          j                            dd	           t          |          	                    t          t          j                              d
           n8# t          $ r+}t          d| d| t          j                   Y d}~nd}~ww xY wt          t          | dd                    t          d| j         dt          j                     dt          j                   ddddfd}dd	 t	          j        | j        | j        t          | dt          j                  |           |r3	 t          |                                           nK# t          $ r Y n?w xY wn:# |r3	 t          |                                           w # t          $ r Y w w xY ww xY wt          d           dS )u:  Deprecated — the dispatcher now runs inside the gateway.

    Left in as a stub so users with the old command in scripts/systemd
    units get a clear migration message instead of a cryptic
    "no such command" error. A ``--force`` escape hatch keeps the old
    standalone daemon alive for the rare edge case where someone truly
    cannot run the gateway (e.g. running on a host that forbids
    long-lived background services), but the default path exits 2
    with guidance so nobody accidentally keeps running two dispatchers
    against the same kanban.db.
    r  Fuy  hermes kanban daemon: DEPRECATED — the dispatcher now runs
inside the gateway. To use kanban:

    hermes gateway start       # starts the gateway + embedded dispatcher

Ready tasks will be picked up on the next dispatcher tick
(default: every 60 seconds). Configure via config.yaml:

    kanban:
      dispatch_in_gateway: true      # default
      dispatch_interval_seconds: 60
      failure_limit: 2              # consecutive non-success attempts before auto-block

Running both the gateway AND this standalone daemon will
race for claims. If you truly need the old standalone
daemon (no gateway available), rerun with --force.r  r(  pidfileNT)r  exist_okzutf-8)encodingz!warning: could not write pidfile r  verbosez;Kanban dispatcher running STANDALONE via --force (interval=zs, pid=z). Ctrl-C to stop. NOTE: if a gateway is also running with dispatch_in_gateway=true (default), you have two dispatchers racing for claims.   r   )	bad_tickslast_warn_atc                n   t          | j                  p	             }t          | j                  }|r|sdxx         dz  cc<   ndd<   d         k    rjt          t	          j                              }|d         z
  dk    r;t          dt          |           dd          dt          j        d	
           |d<   sd S | j	        p)| j
        p"| j        p| j        p| j        p| j        p| j        }|rt          dt          t          t	          j                                         d| j	         dt          | j
                   dt          | j                   dt          | j                   d| j         dt          | j                   dt          | j                   d	           d S d S )Nr  r+  r   r  i,  r  z3] WARN dispatcher stuck: ready queue non-empty for z consecutive ticks but 0 workers spawned successfully. Check profile health (venv, PATH, credentials) and `hermes kanban list --status ready` / `hermes kanban list --status blocked` for recent spawn_failed tasks.T)r  r  z] reclaimed=z	 crashed=z timed_out=z stale=z
 promoted=z	 spawned=z auto_blocked=r  )ry   r  r  r   r   r-  r   r.  r/  r  r  r  r  r  r  rY   )	r  ready_pendingspawned_anynowdid_workHEALTH_WINDOW_ready_queue_nonemptyhealth_stater  s	        r   _on_tickz_cmd_daemon.<locals>._on_tick  sE   S344O8M8M8O8O3;'' 	* 	*%%%*%%%%()L% $55dikk""C\.11S88+ + +1=k1J+ + + 4	 	 	 	 03^, 	FM <S[ <CM <S\ <{<!.<25) 	  	8GC	,,-- 8 8 ]8 8585E5E8 8 //8 88;CI8 8  L8 8 47s{3C3C8 8 !$C$4 5 5	8 8
      	 	r   r   ry   c                     	 t          j                    5 } t          j        |           cddd           S # 1 swxY w Y   dS # t          $ r Y dS w xY w)u  Cheap probe — is there at least one ready+assigned+unclaimed
        task whose assignee maps to a real Hermes profile (i.e. one the
        dispatcher would actually try to spawn for)?

        Filters out tasks assigned to control-plane lanes
        (e.g. ``orion-cc``, ``orion-research``) that are pulled by
        terminals via ``claim_task`` directly — those are correctly idle
        from the dispatcher's perspective, not stuck.
        NF)r   ry  has_spawnable_readyrw   )r|  s    r   r  z*_cmd_daemon.<locals>._ready_queue_nonempty	  s    	#%% 4-d334 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 	 	 	55	s,   A 6A :A :A 
AAr(  )r  r  r(  on_tickz(dispatcher stopped))r   ry   )rM   r-  r.  r/  r   r5  r   r  mkdir
write_textr   r\   getpidOSErrorry   r  
run_daemonrH  r   r   )rG   r  r^  r  r  r  r  r  s       @@@@r   rL  rL    s    4%(( A  #	
 	
 	
 	
& q
 JLLLdIt,,G Y	YMM &&td&CCCMM$$S%5%5$HHHH 	Y 	Y 	YFgFFFFSZXXXXXXXXX	Y 74E2233G		]	 	+-9;;	 	 	
 Z    M!"A66L& & & & & & & &P    
]h!$9WXX		
 	
 	
 	
  	W$$&&&&   	7 	W$$&&&&   	
 

 !!!1s[   A+C 
C;!C66C;(;G &!G 
GGH!G?>H?
H	HHHc                p   | j         r$d | j                             d          D             nd}d}t          dd           t          j                    5 }|                    d                                          }t          |d	                   }ddd           n# 1 swxY w Y   	 	 t          j                    5 }|                    d
|f                                          }ddd           n# 1 swxY w Y   |D ]}t          |t          |d                             }|r|d         |vr2| j
        r|d         | j
        k    rK| j        r|d         | j        k    rd	 |d         rt          j        |d                   nd}n# t          $ r d}Y nw xY w|rd| nd}t          dt          |d                    d|d         dd|d         dd|d         pd d| 
d           t!          j        t          d| j                             n# t&          $ r t          d           Y dS w xY w)z(Live-stream task_events to the terminal.c                ^    h | ]*}|                                 |                                 +S r  )rW   )ri   r  s     r   	<setcomp>z_cmd_watch.<locals>.<setcomp>/	  s-    ???qQWWYY????r   r0  Nr   z'Watching kanban events. Ctrl-C to stop.Tr  z1SELECT COALESCE(MAX(id), 0) AS m FROM task_eventsr  zSELECT e.id, e.task_id, e.kind, e.payload, e.created_at,        t.assignee, t.tenant FROM task_events e LEFT JOIN tasks t ON t.id = e.task_id WHERE e.id > ? ORDER BY e.id ASC LIMIT 200r0   ra   r.   r/   r  r'   r   r  r<   r/  r   10srq  z (@re   r   r  r  )kindssplitr-  r   ry  rz  fetchoner   r{  rH  r.   r/   r   r  rw   r   r   r  r  r  )	rG   r  cursorr|  rz  r}  ru  r  rQ  s	            r   rM  rM  ,	  sE    :	 ??DJ,,S11???? 
 F	
34@@@@				 ll?
 

(** 	 SX	              	0#%% ||A I  (**                  VS4\\22 QvYe33= Qz]dm%C%C; 1X;$+#=#=#:;I,Pdj9666DGG  # # #"GGG#&-5]]]]2E,00 E EAiLG E EyDE E)*:)=#E E@BE E    
 Js3..///7	08    mqqsn   =BB!$B!)H =*C3'H 3C77H :C7;A)H %$F
	H 
FH FA?H H54H5c           
        t          j                    5 }t          j        |          }d d d            n# 1 swxY w Y   t          | dd          r&t	          t          j        |dd                     dS t	          d           dD ]2}t	          d|d	d|d
                             |d                      3|d         rt	          d           t          |d         	                                          D ]Y\  }}d
                    d t          |	                                          D                       }t	          d|dd|            Z|d         }| t	          dt          |           d           dS )Nr   Fr(  r  r   z
By status:)r  r   r   r   r   r   r   r(   r)   	by_statusby_assigneez
By assignee:r  c              3  *   K   | ]\  }}| d | V  dS r  r  r  s      r   rk   z_cmd_stats.<locals>.<genexpr>i	  r  r   r*   oldest_ready_age_secondsz
Oldest ready task age: r  )r   ry  board_statsrM   r-  r   r  r,   r   r  r  r   )rG   r|  r   r  r  r  partsages           r   rN  rN  ]	  s   				 %t$$% % % % % % % % % % % % % % %tVU## djqu===>>>q	,S ; ;919995-11!Q7799::::] +!%"6"<"<">">?? 	+ 	+KCIILLVFLLNN5K5KLLLLLE)s)))%))****
*
+C
5#c((5556661r  c                   t          j                    5 }t          j        || j                  1t	          d| j         t
          j                   	 d d d            dS t          j        || j        | j        | j	        | j
        | j        | j        pt                                 d d d            n# 1 swxY w Y   t	          d| j         d| j	         | j
        r
d| j
         ndz   d| j         z              d	S )
Nr  r  r+  )r   platformchat_id	thread_iduser_idnotifier_profilezSubscribed :r   rX  r   )r   ry  r  r   r-  r.  r/  add_notify_subr  r  r  r  r  rg  r  s     r   rS  rS  q	  sk   				 	
;tT\**214<11
CCCC	
 	
 	
 	
 	
 	
 	
 	
 	$,]DLndl!2Go6G6G		
 	
 	
 	
		
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 

6
6
6
6
6%)^;!!!!=!4<!!" # # # 1s   ?B3 AB33B7:B7c                (   t          j                    5 }t          j        || j                  }d d d            n# 1 swxY w Y   t	          | dd          r&t          t          j        |dd                     dS |st          d           dS |D ]}|                    d          rd|d          nd	}|                    d
          rd|d
          nd	}t          d|d         dd|d          d|d          | d|d          d|            dS )Nr   Fr(  r  r   z(no subscriptions)r  r  r   r  z  owner=r(   r   r   r  r  z  (since event last_event_idr   )	r   ry  list_notify_subsr   rM   r-  r   r  r,   )rG   r|  subsr  throwners         r   rT  rT  	  s   				 7"4667 7 7 7 7 7 7 7 7 7 7 7 7 7 7tVU## djae<<<===q "###q > >&'eeK&8&8@"!K."""b67ee<N6O6OW21/0222UW =1Y<J = =q} = =q| =S = = !/ 2= =5:= = 	> 	> 	> 	>1   ;??c                "   t          j                    5 }t          j        || j        | j        | j        | j                  }d d d            n# 1 swxY w Y   |st          dt          j	                   dS t          d| j                    dS )N)r   r  r  r  z(no such subscription)r  r+  zUnsubscribed from r   )
r   ry  remove_notify_subr   r  r  r  r-  r.  r/  r  s      r   rU  rU  	  s    				 
!$,]DLn
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
  &SZ8888q	
-t|
-
-...1s   .AAAc                <   t          j        | j        | j                  }|&t	          d| j         dt
          j                   dS t
          j                            |           |	                    d          st
          j                            d           dS )N)
tail_bytesz(no log for u#    — task may not have spawned yet)r  r+  
r   )
r   read_worker_logr   r   r-  r.  r/  stdoutwriteendswith)rG   contents     r   rO  rO  	  s     $)DDDGNT\NNN:	 	 	 	qJWD!! 
1r   c                D   t          |           }|t          dt          j                   dS t	          j                    5 }t	          j        || j        fi |}ddd           n# 1 swxY w Y   t          | dd          r0t          t          j
        d |D             dd                     d	S |st          d
| j         d           d	S t          dddddddddddd           t          |d          D ] \  }}|j        pt          t          j                              }t          d	||j        z
            }|dk     r| d}n|dk     r	|dz   d}n	|dz  dd}|j        p|j        sdn|j        }	t          |dd|	dd|j        pddd|ddt)          |j                   	           |j        r9|j                                        d	         dd          }
t          d!|
            |j        rt          d"|j        dd                      "d	S )#z Show attempt history for a task.NzBkanban runs: pass both --state-type and --state-name, or omit bothr  r(  r   Fc                    g | ]G}|j         |j        |j        |j        |j        |j        |j        |j        |j        |j	        |j
        d HS )r0   r   r-   r   r=   r#  r   r   r!  r"  r  r(  rt  s     r   r  z_cmd_runs.<locals>.<listcomp>	  sb     
 
 
  dqyAH9ALJ19ajl
 
 
 
r   r  r   z(no runs yet for r   #3sr(   OUTCOME12sPROFILE16sELAPSEDz>8sz	  STARTEDr+  r  r  r  r  z.1fr  z	(running)3dre   d   u	        → u	        ✖ )rP   r-  r.  r/  r   ry  r?  r   rM   r   r  	enumerater#  r   r   rH  r=   r   r-   r   r   r   rI  r   )rG   rJ  r|  r   re  ru  endrS  rT  r   r   s              r   rP  rP  	  s   
D
!
!C
{P	
 	
 	
 	
 q				 7|D$,66#667 7 7 7 7 7 7 7 7 7 7 7 7 7 7tVU## 
dj 
 
 
 
 
 %) ) ) 	* 	* 	* q 1$,111222q	S
Q
Q
Qy
Q
Q
Q	
Q
Q
Q
Q
Q
Q
QRRR$"" / /1j,C	,,aq|+,,R<<BBt^^rM$$$BBdN))))B)L1: K18cccccc)9cccc"cccGTUT`LaLaccddd9 	)i**,,Q/5G'g''(((7 	/-agdsdm--...1s   A''A+.A+c                    t          j                    5 }t          j        || j                  }d d d            n# 1 swxY w Y   t	          |           dS Nr   )r   ry  build_worker_contextr   r-  )rG   r|  r   s      r   rV  rV  	  s    				 ;&tT\::; ; ; ; ; ; ; ; ; ; ; ; ; ; ;	$KKK1r  c           
        ddl m} t          t          | dd                    }t          | dd          }t          | dd          pt	                      }t          t          | dd                    }| j        r|rt          d	t          j        
           dS |r`|	                    |          }|sGd|rd|ndz   dz   }|r%t          t          j        ddd                     nt          |           dS n-| j        r	| j        g}nt          dt          j        
           dS d}d}	|D ]}
|                    |
|          }|j        r|dz  }n|	dz  }	|r;t          t          j        |j        |j        |j        |j        d                     h|j        r.|j        r
d|j        nd}t          d|j         d|            t          d|j         d|j         t          j        
           |s
|dk    rdndS |dk    s|sdndS )z{Flesh out a triage task (or all of them) via auxiliary LLM,
    then promote to todo. Thin wrapper over ``kanban_specify``.r   )kanban_specifyr   Fr/   Nr  r   0kanban: pass either a task id OR --all, not bothr  r(  r/   No triage tasks for tenant r   r  )	specifiedr  z+kanban: specify requires a task id or --allr  r+  )r   r  r   	new_title    — retitled: 
Specified u	    → todozkanban: specify r  )rA  r8  ry   rM   rg  r   r-  r.  r/  list_triage_idsr   r  specify_taskr  r   r?  )rG   specall_flagr/   r  	want_jsonrw  msgok_count
fail_countrn  r   title_suffixs                r   rW  rW  	  s    211111GD,6677HT8T**FT8T**?o.?.?FWT651122I|  >	
 	
 	
 	
 q ""&"11 
	!06>,&,,,B@ 
  djq1!=!=>>????c


1
	 
 |n9	
 	
 	
 	
 qHJ  ##C#77: 	MHH!OJ 	$*"?j!.$.	        Z 	 $7'"3777 
 GwGGGGHHHHF7?FFgnFFZ      )MMqqq( AS11q0r   c                   ddl m} t          t          | dd                    }t          | dd          }t          | dd          pt	                      }t          t          | dd                    }| j        r|rt          d	t          j        
           dS |r`|	                    |          }|sGd|rd|ndz   dz   }|r%t          t          j        ddd                     nt          |           dS n-| j        r	| j        g}nt          dt          j        
           dS d}|D ](}	|                    |	|          }
|
j        r|dz  }|rGt          t          j        |
j        |
j        |
j        |
j        |
j        |
j        d                     o|
j        r|
j        rR|
j        rKd                    |
j                  }t          d|
j         dt'          |
j                   d| d           |
j        r
d|
j        nd}t          d|
j         d|            t          d|
j         d|
j         t          j        
           *|s
|dk    rdndS |dk    s|sdndS ) zFan a triage task (or all of them) out into a graph of child
    tasks via the auxiliary LLM, routed to specialist profiles by
    description. Thin wrapper over ``kanban_decompose``.r   )kanban_decomposer   Fr/   Nr  r   r9  r  r(  r:  r;  r<  r   r  )
decomposedr  z-kanban: decompose requires a task id or --allr>  r+  )r   r  r   fanoutr>  r?  r  zDecomposed u    → z children (z); root promoted to todor@  rA  u    → todo (no fanout)zkanban: decompose r  )rA  rL  ry   rM   rg  r   r-  r.  r/  rB  r   r  decompose_taskr  r   rN  r>  r?  r  rY   )rG   decomprE  r/   r  rF  rw  rG  rH  rn  r   child_summaryrJ  s                r   rX  rX  ,
  sm    655555GD,6677HT8T**FT8T**?o.?.?FWT651122I|  >	
 	
 	
 	
 q $$F$33 
	!06>,&,,,B@ 
  djA!>!>??@@@@c


1
	 
 |n;	
 	
 	
 	
 qH " "''F';;: 	MH 	$*"?j!.!.$.$.        Z 	~ '"3  $		'*; < <I'/ I IG<M8N8N I I!.I I I    (;g&7;;; 
 1 1 1".1 1   
 HW_HHHHZ      )MMqqq(AS11q0r   c           	        ddl }t          j                    }d}t          j                    5 }|                    d                                          }ddd           n# 1 swxY w Y   |D ]}|d         dk    rt          |d         p
||d         z            }	 |                                }n# t          $ r Y Qw xY w	 |	                    |                                           n# t          $ r Y w xY w|                                r0|                                r|                    |d	           |d
z  }t          | dd          }t          | dd          }	t          j                    5 }t          j        ||dz  dz            }
ddd           n# 1 swxY w Y   t          j        |	dz  dz            }t#          d| d|
 d| d           dS )z^Remove scratch workspaces of archived tasks, prune old events, and
    delete old worker logs.r   NzNSELECT id, workspace_kind, workspace_path FROM tasks WHERE status = 'archived'r8   rT   r9   r0   T)ignore_errorsr+  event_retention_daysr   log_retention_days   r  )older_than_secondszGC complete: z workspace(s), z event row(s), z log file(s) removed)shutilr   workspaces_rootry  rz  r{  r   resolver  relative_tor2  rx  is_dirrmtreerM   	gc_eventsgc_worker_logsr-  )rG   rX  scratch_root
removed_wsr|  r}  rz  r]   
event_dayslog_daysremoved_eventsremoved_logss               r   rY  rY  }
  s    MMM%''LJ				 ||\
 

(** 	                  I--C()GlSY.FHH	<<>>DD 	 	 	H		\11334444 	 	 	H	 ;;== 	T[[]] 	MM$dM333!OJ5r::Jt1266H				 
Z"_t%;
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $#b=4/  L 
 O* O OO O,8O O O P P P1sG   (A!!A%(A%B33
C ?C 'C,,
C98C96FF#&F#uU  **/kanban** — manage the shared task board.

Common subcommands:
  `list` (alias `ls`)   List tasks on the current board
  `show <id>`           Task details + comments + events
  `stats`               Per-status / per-assignee counts
  `create <title>…`     Create a task (auto-subscribes you to events)
  `comment <id> <msg>`  Append a comment
  `complete <id>…`      Mark task(s) done
  `block <id> [reason]` Mark blocked; `schedule <id> [reason]` parks time-delay work; `unblock <id>` to revive
  `assign <id> <profile>`  Reassign
  `boards list`         Show all boards
  `assignees`           Known profiles + counts
  `context <id>`        Full worker-context dump
  `runs <id>`           Attempt history
  `log <id>`            Worker log

Run `/kanban <subcommand> -h` for arguments. Read-only commands are safe while an agent is running.restc                   ddl }ddl}| r(|                                 rt          j        |           ng r
d         dv rt
          S t          j        dd          }d|_        |	                    d          }t          |          d	_        d_        j        D ]L}t          |t          j                  r0|j                                        D ]\  }}d
| |_        d|_        Mdfd}|                                }	|                                }
	 |                    |	          5  |                    |
          5                                }ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   n# t*          $ ru}|	                                                                }|
                                                                }|j        dv r	|r|cY d}~S |p|}|rd| ndcY d}~S d}~wt          j        $ r}d |             d| cY d}~S d}~ww xY w|                    |	          5  |                    |
          5  	 t5          |           n@# t*          $ r Y n4t6          $ r(}t9          d| t:          j                   Y d}~nd}~ww xY wddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   |	                                                                }|
                                                                }|r	|r| d| S |r|n|pdS )u  Execute a ``/kanban …`` string and return captured stdout/stderr.

    ``rest`` is everything after ``/kanban`` (may be empty).  Used from
    both the interactive CLI (``self._handle_kanban_command``) and the
    gateway (``_handle_kanban_command``) so formatting is identical.
    r   N>   -h--helpr   r#   z/kanban-wrapF)progadd_help_topr   z/kanbanz/kanban r   r   c                 0   rnj         D ]f} t          | t          j                  rJ| j                            d                   }|(|                                                                c S g                                                                S r5  )_actionsrD  rZ   _SubParsersActionr   r,   format_usager  )_action	subparserr   tokenss     r   _usage_for_errorz#run_slash.<locals>._usage_for_error
  s     	A(1 A Agx'ABB A ' 3 3F1I > >I ,(5577>>@@@@@))++22444r   >   Nr   u   ⚠ /kanban usage error
u   ⚠ /kanban usage errorr   zerror: r  z(no output)r   r   )io
contextlibrW   shlexr  _SLASH_KANBAN_HELPrZ   ArgumentParserexit_on_errorr   r  rj  rn  rD  ro  r   r  StringIOredirect_stdoutredirect_stderr
parse_args
SystemExitgetvaluer  codeArgumentErrorra  rw   r-  r.  r/  )rf  rv  rw  _wrap_top_subrq  _name_choicert  buf_outbuf_errrG   r^  outr  r6   r   rs  s                   @@r   	run_slashr  
  s    III"&?4::<<?U[RF  "VAY"???!! #%HHHEE###00H **M"M"'M ) . .gx9:: 	.")/"7"7"9"9 . .w1%11(-%%5 5 5 5 5 5 5 kkmmGkkmmGG''00 	4 	4*2L2LW2U2U 	4 	4 ++F33D	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 Y Y Y  ''))  ''))8y  S JJJJJJzc59X14111?XXXXXXX! G G GF+;+;+=+=FFFFFFFFFFG 
	#	#G	,	, 4 4j.H.H.Q.Q 4 4	44     	 	 	D 	4 	4 	4/C//
333333333	44 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 




#
#
%
%C





#
#
%
%C
 s 133C0=1s   F 3F	E+F+E/	/F2E/	3F6F FF 	F
F 
H4AH0H46HH4H4H/)H4/H4K"K $I43K 4
J1>K  	J1	J,'K ,J11K 4K K	KK	KKK)r   r   r   r   )r    r!   r   r   )r    r!   r   r4   )rG   rH   r   rI   )rQ   r   r   rR   )rQ   rc   r   rc   )r   ro   )r~   r   r   r   )rG   rH   r   r   ru  )r   r   r   rp  )r   r   )r   r   r   r   )rf  r   r   r   )S__doc__
__future__r   rZ   r   r\   rx  r.  r   pathlibr   typingr   r   rA  r   r   r   r  re  r	   r
   r   r+   r   r3   rF   rP   rb   rn   r}   r  ra  rg  r0  r~  ri  rj  rk  rl  rm  rn  ro  r  r6  rQ  rR  r7  r8  r9  r:  r;  r<  r=  r>  r?  r@  rA  rB  r  rC  rD  rE  rF  rG  rH  rI  rJ  rK  rL  rM  rN  rS  rT  rU  rO  rP  rV  rW  rX  rY  ry  r  r  r   r   <module>r     s    # " " " " "   				  



                        & & & & & & ) ) ) ) ) ) ] ] ] ] ] ] ] ] ] ]  ? ? ? ?N N N N   20 0 0 0   2   3 3 3 3tC
 C
 C
 C
TB B B BR
 
 
 
"   8          F   <   (   *          ,\ \ \ \2. . . .b      &< < < <~   >* * * *Zi i i iX          .@ @ @ @F         ,    	 	 	 	*" *" *" *"Z   8" " " "," " " "," " " ",0" 0" 0" 0"f" " " "8   $h h h hVJ J J JZ. . . .b   (   "   "   	 	 	 	, , , ,^   F1 F1 F1 F1RN1 N1 N1 N1b& & & &Z .K2 K2 K2 K2 K2 K2r   