
    iF                        d Z ddlmZ ddlZddlmZ  ej                  d      Z ej                  d      Z ej                  d      Z	ddZ
dd	Zdd
ZddZddZddZy)a9  Task ID parsing utilities (V2).

Supports unified parsing of task IDs across files, branches, and CLI args.

V2 pattern:
    task-<digits>(_<phase>)?(_<parallel>)?(+<retry>)?
    - phase:    \d+\.\d+   (e.g. _1.2)
    - parallel: [a-z]         (e.g. _a)
    - retry:    \d+           (e.g. +1)

Examples
--------
- ``task-2469``                 -> base only
- ``task-2469+1``               -> retry suffix preserved
- ``task-2469_1.2``             -> phase
- ``task-2469_1.2_a``           -> phase + parallel
- ``task-2469_1.2_a+3``         -> phase + parallel + retry
    )annotationsN)OptionalzZ^task-(?P<num>\d+)(?:_(?P<phase>\d+\.\d+))?(?:_(?P<parallel>[a-z]))?(?:\+(?P<retry>\d+))?$z,^task-\d+(?:\.\d+)*(?:\.dev\d+)?(?:\.done)?$zXtask-(?P<num>\d+)(?:_(?P<phase>\d+\.\d+))?(?:_(?P<parallel>[a-z]))?(?:\+(?P<retry>\d+))?c                z   t         j                  | j                               }|sdddddS d|j                  d       }|j                  d      rd|j                  d       nd}|j                  d      rd|j                  d       nd}|j                  d      rd	|j                  d       nd}||||dS )
a  Parse a V2 task id string into structural components.

    Returns a dict with keys ``base``, ``phase``, ``parallel``, ``retry``.
    For inputs that don't match, returns dict with all values ``None`` and
    ``base`` left as the original string for caller diagnostics.

    Examples
    --------
    >>> parse_task_id_v2("task-2469+1")
    {'base': 'task-2469', 'phase': None, 'parallel': None, 'retry': '+1'}
    >>> parse_task_id_v2("task-2469_1.2_a+3")
    {'base': 'task-2469', 'phase': '_1.2', 'parallel': '_a', 'retry': '+3'}
    N)basephaseparallelretrytask-numr   _r   r	   +)TASK_ID_V2_PATTERNmatchstripgroup)smr   r   r   r	   s         G/home/jay/workspace/.worktrees/task-2487+1-dev2/utils/task_id_parser.pyparse_task_id_v2r   *   s     	  +AtMM1775>"#D&'ggg&6a !"DE,-GGJ,?177:&'(TH&'ggg&6a !"DE5hOO    c                L    t         j                  | j                               duS )z5Return True iff ``s`` matches the V2 pattern exactly.N)r   r   r   r   s    r   is_valid_task_idr   D   s    ##AGGI.d::r   c                    t        | t              sy| j                         } t        t        j                  |             xs t        t        j                  |             S )u   V2 task id 또는 legacy dot-phase task id를 PASS.

    legacy 예시: task-9.1, task-1234.5, task-648.1.dev1, task-648.1.dev1.done
    V2 예시:    task-2485+1, task-2487+1, task-2469_1.2_a+3
    F)
isinstancestrr   boolr   r   _LEGACY_DOTPHASE_PATTERNr   s    r   is_valid_task_id_with_legacyr   I   sJ     a		A"((+,W5M5S5STU5V0WWr   c                   d| j                  d       g}| j                  d      r#|j                  d| j                  d              | j                  d      r#|j                  d| j                  d              | j                  d      r#|j                  d| j                  d              dj                  |      S )	Nr
   r   r   r   r   r	   r    )r   appendjoin)r   partss     r   _reassemble_from_matchr%   U   s    QWWU^$%&Ewwwq)*+,wwzq,-./wwwq)*+,775>r   c                   t        | t              r| sy| j                  dd      d   }d|v r|j                  dd      d   n|}t        j	                  |      }|rt        |      S t        j                  |       }|rt        |      S y)zExtract a task id from a filename or path.

    Examples
    --------
    >>> extract_task_id_from_filename("memory/tasks/task-2469+1.md")
    'task-2469+1'
    >>> extract_task_id_from_filename("task-2469_1.2_a+3.md")
    'task-2469_1.2_a+3'
    N/   .r   )r   r   rsplitr   r   r%   _TASK_ID_LOOSE_PATTERNsearch)filenamebasenamestemr   s       r   extract_task_id_from_filenamer1   `   s     h$H sA&r*H),8??3"1%hD  &A%a(( 	%%h/A%a((r   c                n    t        | t              r| syt        j                  |       }|syt	        |      S )zExtract a task id from a branch name.

    Examples
    --------
    >>> extract_task_id_from_branch("task/task-2467+3-dev6")
    'task-2467+3'
    >>> extract_task_id_from_branch("task/task-2469_1.2-dev2")
    'task-2469_1.2'
    N)r   r   r,   r-   r%   )branchr   s     r   extract_task_id_from_branchr4   }   s4     fc"&%%f-A!!$$r   )r   r   returndict)r   r   r5   r   )r   objectr5   r   )r   zre.Matchr5   r   )r.   r   r5   Optional[str])r3   r   r5   r8   )__doc__
__future__r   retypingr   compiler   r   r,   r   r   r   r%   r1   r4    r   r   <module>r?      sw   & # 	   RZZa  &2::3 
 $_ 
P4;
	X:%r   