
    sjuc                    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m	Z	 ddl
mZ ddlmZmZmZ ddlmZ ddlmZmZmZ dd	lmZ  ej                    Zd
ZdZdZdZdZdZ ed           G d d                      Z ed           G d d                      Z dfdZ!dfdZ"dgdZ#dhdZ$e	did            Z%djd"Z&dd#dkd(Z'dld-Z(dmd/Z)dnd2Z*dod6Z+dpd7Z,dqd9Z-drd<Z.dsd=Z/dtd?Z0dudAZ1dvdBZ2dwdEZ3dwdFZ4dxdHZ5	 dydzdIZ6d{dKZ7d|dMZ8ddddNdOd}dSZ9dNdTd~dVZ:ddWdXdNdYdd]Z;dd`Z<ddadddZ=ddeZ>dS )a  Coding verification evidence ledger.

This module records what the agent actually proved while working in a code
workspace. It is deliberately passive: it never decides to run a suite, never
blocks completion, and never upgrades targeted checks into "repo green".
    )annotationsN)contextmanager)	dataclass)datetime	timedeltatimezone)Path)AnyIteratorOptionalget_hermes_homei     d   i'  )zhermes-verify-zhermes-ad-hoc-   T)frozenc                  (    e Zd ZU ded<   dZded<   dS )_ShellSegment	list[str]tokensN
str | Nonefollowing_operator)__name__
__module____qualname____annotations__r        ?/home/agent/.hermes/hermes-agent/agent/verification_evidence.pyr   r   !   s0         %)))))))r   r   c                  |    e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   dZded<   dS )VerificationEvidencez,A classified command result worth recording.strcommandcanonical_commandkindscopestatusint	exit_codecwdroot
session_id output_summaryN)r   r   r   __doc__r   r.   r   r   r   r!   r!   '   s}         66LLLIIIJJJKKKNNNHHHIIIOOONr   r!   returnr"   c                 b    t          j        t          j                                                  S N)r   nowr   utc	isoformatr   r   r   _utc_nowr6   7   s     <%%//111r   c                     t          j        t          j                  t	          t
                    z
                                  S )N)days)r   r3   r   r4   r   _MAX_EVIDENCE_AGE_DAYSr5   r   r   r   _retention_cutoffr:   ;   s1    L&&8N)O)O)OOZZ\\\r   r	   c                 $    t                      dz  S )Nverification_evidence.dbr   r   r   r   _db_pathr=   ?   s    999r   sqlite3.Connectionc                 \   ddl m}  t                      }|j                            dd           t          j        |          }t
          j        |_        	  | |d           |	                    d           t          |           n## t          $ r |                                  w xY w|S )Nr   )apply_wal_with_fallbackT)parentsexist_okr<   )db_labelzPRAGMA busy_timeout=5000)hermes_stater@   r=   parentmkdirsqlite3connectRowrow_factoryexecute_ensure_schema	Exceptionclose)r@   pathconns      r   _connectrQ   C   s    444444::DKdT222?4  D{D/IJJJJ/000t    	

	
 Ks   1B	 	 B)Iterator[sqlite3.Connection]c               #     K   t                      } 	 | 5  | V  ddd           n# 1 swxY w Y   |                                  dS # |                                  w xY w)u  Open a connection, commit/rollback on exit, and ALWAYS close it.

    ``sqlite3.Connection.__enter__``/``__exit__`` only commit or roll back the
    transaction; they do not close the connection. Using ``with _connect()``
    alone therefore leaks a connection — and its WAL/SHM file descriptors — on
    every call, deferring the close to the garbage collector, which over a
    long-running process can exhaust ``RLIMIT_NOFILE`` (the cron-ledger sibling
    of this bug was #69567 / PR #69594).
    N)rQ   rN   rP   s    r   _transactionrU   V   s       ::D 	 	JJJ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	



s&   A %A )A )A ArP   Nonec                (   |                      d           |                      d           |                      d           |                      d           |                      dt          t                    f           |                                  d S )Nz
        CREATE TABLE IF NOT EXISTS meta (
            key TEXT PRIMARY KEY,
            value TEXT NOT NULL
        )
        a  
        CREATE TABLE IF NOT EXISTS verification_events (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            created_at TEXT NOT NULL,
            session_id TEXT NOT NULL,
            cwd TEXT NOT NULL,
            root TEXT NOT NULL,
            command TEXT NOT NULL,
            canonical_command TEXT NOT NULL,
            kind TEXT NOT NULL,
            scope TEXT NOT NULL,
            status TEXT NOT NULL,
            exit_code INTEGER NOT NULL,
            output_summary TEXT NOT NULL
        )
        a9  
        CREATE TABLE IF NOT EXISTS verification_state (
            session_id TEXT NOT NULL,
            root TEXT NOT NULL,
            last_event_id INTEGER,
            last_edit_at TEXT,
            changed_paths_json TEXT NOT NULL DEFAULT '[]',
            PRIMARY KEY (session_id, root)
        )
        z
        CREATE INDEX IF NOT EXISTS idx_verification_events_session_root
        ON verification_events(session_id, root, id DESC)
        zDINSERT OR REPLACE INTO meta(key, value) VALUES ('schema_version', ?))rK   r"   _VERIFY_SCHEMA_VERSIONcommitrT   s    r   rL   rL   i   s    LL	   	LL	  $ 	LL		   	LL	   	LLN	#	$	$&   	KKMMMMMr   posixr#   r[   boollist[_ShellSegment]c                  g }d}d}d}d}|t          |           k     r| |         }|rd}|dz  }&|dk    r|dk    rd}|dz  }:|r||k    rd}|dz  }J|dv r|}|dz  }Vd}|                     d	|          r| ||d
z            }nA|dk    rd}n8|dv r|}n1|dk    r+|dk    s| |dz
           dvr|                     d|          s|}||dz  }| ||                                         }	|	sg S |                    |	|f           ||dk    rdnt          |          z  }|}|t          |           k     |s|rg S | |d                                         }
|
r|                    |
df           n|r|d         d         dvrg S g }|D ][\  }	}	 t	          j        |	|          }n# t          $ r g cY c S w xY w|sg c S |                    t          ||                     \|S )zKTokenize top-level shell commands while preserving their control operators.r   NFr   \'T>   "r`   )&&|||&   
;z;|&z<>)z&>z&>>>   rg   rZ   )r   r   )len
startswithstripappendshlexsplit
ValueErrorr   )r#   r[   raw_segmentsstartquoteescapedindexcharoperatorrawtrailingsegmentsr   s                r   _split_shell_segmentsr{      s   13LEEGE
#g,,

u~ 	GQJE4<<ESLLGQJE 	u}}QJE:EQJE0%88 	uUQY/HHT\\HHT\\HHCKK!wuqy1==&&}e<<  > HQJEeEk"((** 	IS(O,,,ddllH5W #g,,

Z   	uvv$$&&H Xt,----	 ,r*1-U::	$&H% S SX	[E222FF 	 	 	IIIII	 	IIIVQQQRRRROs   F((F98F9rz   match_indexr(   r)   c                   | rd|cxk    rt          |           k     sn dS t          d | D                       rdS d}t          | dd                   D ]\  }}|j        dk    r|dz   }||k     rdS | |d         }d |dd         D             }t          d	 |D                       rdS t          |          dk    rd
S t	          |          dk    ot          d |D                       S )zCWhether the shell's status proves the matched segment's own status.r   Fc              3  ,   K   | ]}|j         d k    V  dS )rh   Nr   .0segments     r   	<genexpr>z/_exit_status_is_attributable.<locals>.<genexpr>   s*      
E
E7%,
E
E
E
E
E
Er   Nri   rg   r   c                    g | ]	}|j         
S r   r   r   s     r   
<listcomp>z0_exit_status_is_attributable.<locals>.<listcomp>   s    III+IIIr   c              3     K   | ]}|d v V  	dS )>   |rd   rc   Nr   r   rw   s     r   r   z/_exit_status_is_attributable.<locals>.<genexpr>   s(      
C
CX8((
C
C
C
C
C
Cr   Tc              3  "   K   | ]
}|d k    V  dS )rb   Nr   r   s     r   r   z/_exit_status_is_attributable.<locals>.<genexpr>   s'      &R&RHx4'7&R&R&R&R&R&Rr   )rj   any	enumerater   r(   all)rz   r|   r)   sequence_startru   r   sequence	operatorss           r   _exit_status_is_attributabler      s9     1;;;;c(mm;;;;u

E
EH
E
E
EEE uN#HSbSM22 ' 'w%,,"QYN^##u(HII8CRC=IIII

C
C
C
C
CCC u
8}}ty>>QR3&R&R	&R&R&R#R#RRr   tokenc                    |                                  } |                     d          r| dd          } |                     d          | S )Nz./re   )rl   rk   )r   s    r   _clean_tokenr      sO    KKMME


4
 
  abb	 

4
 
  Lr   	canonicalr   c                d    	 d t          j        |           D             S # t          $ r g cY S w xY w)Nc                0    g | ]}|t          |          S r   r   r   ts     r   r   z%_canonical_tokens.<locals>.<listcomp>  s#    EEEA1EQEEEr   )rn   ro   rp   )r   s    r   _canonical_tokensr     sI    EEY)?)?EEEE   			s     //r   needleOptional[int]c                   | r"|r t          |          t          |           k    rd S d | D             }t          dt          |          t          |          z
  dz             D ]$}|||t          |          z            |k    r|c S %d S )Nc                ,    g | ]}t          |          S r   r   r   s     r   r   z%_find_subsequence.<locals>.<listcomp>  s    ///1|A///r   r   r   )rj   range)r   r   cleanedidxs       r   _find_subsequencer     s      3v;;V#<#<t/////GQGs6{{2Q677  3sS[[(()V33JJJ 44r   c                H   t          |           }|r|d         dk    r
|dd         }|rVd|d         v rL|d                             d          s1|dd         }|r%d|d         v r|d                             d          1|r |d         dv r|dd         }|r
|d         dv |S )zDRemove harmless command prefixes before matching canonical commands.r   envr   N=->   timenoglobr#   )listrk   )r   	remainings     r   _strip_command_prefixr     s    VI "Yq\U**abbM	
 "y|++IaL4K4KC4P4P+abbM	  "y|++IaL4K4KC4P4P+
 "	!(EEEabbM	  "	!(EEEr   list[list[str]]c                ~   | g}t          |           dk    r7| d         dk    r+| d         }| d         }|dv r|                    ||g           t          |           dk    r1d| d         v r'|                    d| d         gd	| d         gg           | d
gk    r$|                    g dg dg dg dg dg           |S )zFReturn command spellings equivalent to the detected canonical command.   r   runr   re   >   bunnpmpnpmyarn/bashshpytest)python-mr   )python3r   r   )uvr   r   )poetryr   r   )pipenvr   r   )rj   rm   extend)r   
candidatespackage_managerscript_names       r   _equivalent_needlesr   #  s   J
6{{aF1I.. )Qi<<<<===
6{{aC6!9,,FF1I.vay0ABCCC(***+++'''++++++	
 	
 	
 r   canonical_commandsOptional[tuple[str, list[str]]]c                ^   t          |           }|D ]}t          |          }|st          |          D ]v\  }}t          |j                  }t          |          D ]M}	|dt          |	                   |	k    r0t          |||          r||t          |	          d         fc c c S NwdS )zEReturn ``(canonical, trailing_args)`` for the first detected command.N)r{   r   r   r   r   r   rj   r   )
r#   r   r)   rz   r   r   ru   r   candidate_tokens	candidates
             r   _find_canonical_matchr   :  s     %W--H' H H	"9-- 	'11 	H 	HNE74W^DD088 H H	$_c)nn_5BB4XuiPP C %&6s9~~&GGGGGGGGGH	H 4r   c                    |                                  t          fddD                       rdS t          fddD                       rdS dv rdS dv sd	v rd	S d
v rdvrd
S dS )Nc              3      K   | ]}|v V  	d S r2   r   r   wordlowereds     r   r   z$_kind_for_command.<locals>.<genexpr>S  s'      
B
Bt47?
B
B
B
B
B
Br   )linteslintruffr   c              3      K   | ]}|v V  	d S r2   r   r   s     r   r   z$_kind_for_command.<locals>.<genexpr>U  s'      
U
Ut47?
U
U
U
U
U
Ur   )	typechecktscmypypyrighttyr   buildfmtformatchecktest)lowerr   )r   r   s    @r   _kind_for_commandr   Q  s    ooG

B
B
B
B'A
B
B
BBB v

U
U
U
U'T
U
U
UUU {'w8w..x'fG33w6r   argc                    | r|                      d          sd| v rdS d| v p1d| v p-d| v p)|                     d          p|                      d          S )	Nr   r   Fr   r_   z::)z.pyz.jsz.jsxz.tsz.tsxz.rsz.goz.java)test_testsspec	__tests__)rk   endswith)r   s    r   _looks_like_targetr   `  s     #..%% us
 	C3;	C3;	C <<TUU	C >>ABBr   argsc                <    t          d | D                       rdndS )Nc              3  4   K   | ]}t          |          V  d S r2   )r   )r   r   s     r   r   z"_scope_for_args.<locals>.<genexpr>m  s+      EE/44EEEEEEr   targetedfull)r   )r   s    r   _scope_for_argsr   l  s(    EEEEEEEQ::6Qr   c                p   | r|                      d          rdS 	 t          |                                           }|                                sdS |                                }t          t          j                                                              }||k    p||j        v S # t          $ r Y dS w xY w)Nr   F)	rk   r	   
expanduseris_absoluteresolvetempfile
gettempdirrA   rM   )r   rO   resolved	temp_roots       r   _is_under_temp_dirr   p  s     E$$S)) uE{{%%''!! 	5<<>>,..//7799	9$E	X5E(EE   uus   5B' AB' '
B54B5r+   str | Path | Nonec                   |sdS 	 t          |                                                                           }t          |                                                                          }||k    p||j        v S # t          $ r Y dS w xY wNF)r	   r   r   rA   rM   )r   r+   rO   	root_paths       r   _is_under_rootr   ~  s     uE{{%%''//11JJ))++3355	y =I$==   uus   A4A; ;
B	B	c                    	 t          |                                           j        }n# t          $ r Y dS w xY w|                    t
                    ot          |           ot          | |           S r   )r	   r   namerM   rk   _AD_HOC_SCRIPT_NAME_PREFIXESr   r   )r   r+   r   s      r   _is_temp_script_pathr     s    E{{%%'',   uu 	455 	,u%%	,ud+++s   &) 
77Optional[list[str]]c                2   t          |           }|sd S |d         }t          ||          r
|dd          S |dv r]t          |dd          d          D ]C\  }}|dk    rt          ||          r||dz   d          c S |                    d          s d S Dd S )Nr   r   >   r   r   nodeperlrubyr   r   )rr   z--r   )r   r   r   rk   )r   r+   r   r#   r   r   s         r   _ad_hoc_script_argsr    s    ,V44 tq!GGT** $##MMM#$4QRR$8BBB 	 	JC}}#E400 2'a1111##C(( tt4r   c                    dD ]V}t          | |          }t          |          D ]3\  }}t          |j        |          }|t	          |||          r|c c S 4Wd S )N)TFrZ   )r{   r   r  r   r   )r#   r+   r)   r[   rz   ru   r   trailing_argss           r   _find_ad_hoc_matchr    s      % %(>>>'11 	% 	%NE7/EEM(-I%. .( %$$$$$	% 4r   outputc                    | pd                                 }t          |          t          k    r|S t          dz  }t          |z
  }|d |         dt          |          t          z
   dz   || d          z   S )Nr-   r   z
... [z chars omitted] ...
)rl   rj   _MAX_OUTPUT_SUMMARY_CHARS)r  textheadtails       r   _summarize_outputr    s    Lb!!D
4yy---$)D$t+DUdU
PCII 99
P
P
P	Q
uvv,	r   r,   c                   t                      }|                     d||||t          f           |                     d||f           |                     d|f           |                     dt          f           dS )z?Bound ledger growth without deleting the current state pointer.a!  
        DELETE FROM verification_events
        WHERE session_id = ?
          AND root = ?
          AND id NOT IN (
              SELECT id FROM verification_events
              WHERE session_id = ? AND root = ?
              ORDER BY id DESC
              LIMIT ?
          )
        aQ  
        DELETE FROM verification_state
        WHERE (
            last_edit_at IS NOT NULL
            AND last_edit_at < ?
        )
        OR (
            last_edit_at IS NULL
            AND last_event_id IN (
                SELECT id FROM verification_events
                WHERE created_at < ?
            )
        )
        z
        DELETE FROM verification_events
        WHERE created_at < ?
          AND id NOT IN (
              SELECT last_event_id FROM verification_state
              WHERE last_event_id IS NOT NULL
          )
        aD  
        DELETE FROM verification_events
        WHERE id NOT IN (
            SELECT id FROM verification_events
            ORDER BY id DESC
            LIMIT ?
        )
          AND id NOT IN (
              SELECT last_event_id FROM verification_state
              WHERE last_event_id IS NOT NULL
          )
        N)r:   rK   _MAX_EVENTS_PER_SESSION_ROOT_MAX_TOTAL_UNREFERENCED_EVENTS)rP   r,   r+   cutoffs       r   _prune_old_eventsr    s      FLL
	 
T:t-IJ   	LL	 
  " 	LL	 
	
 
 
 	LL	 
()    r   r-   r*   r,   r)   r  r*   r   Optional[VerificationEvidence]c               n   | rt          | t                    sdS 	 ddlm}  ||          }n# t          $ r d}Y nw xY w|sdS t          |                    d          pg           }t          | |t          |                    }d}	|;|s9t          | |                    d          t          |                    }
|
d|
f}d}	|dS |\  }}t          | ||	rd	nt          |          |	rd
nt          |          t          |          dk    rdndt          |          t          t          |pd                                                    t          |                    d          p"t          |pd                                                    t          |pd          t          |          
  
        S )zDClassify a terminal command as verification evidence, if applicable.Nr   project_facts_forverifyCommandsFr+   zad-hoc verification scriptTad_hocr   passedfailed.default
r#   r$   r%   r&   r'   r)   r*   r+   r,   r.   )
isinstancer"   agent.coding_contextr  rM   r   getr   r(   r  r!   r   r   r	   r   r  )r#   r*   r,   r)   r  r  factsverify_commandsmatch	is_ad_hocad_hoc_argsr   r  s                r   classify_verification_commandr'    s     *Wc22 t::::::!!#&&    t599%566<"==O!'?C	NNKKEI}_}(%))F2C2CS^^TT"1;?EI}t$I}#"DXX(9)(D(D%Ijj?=+I+Iy>>Q..xxHi..SZC  ((**++6""@d3:#&6&6&>&>&@&@AAz.Y//(00   s   - <<)r  Optional[dict[str, Any]]c                P    t          | ||||          }|dS t          |          S )zERecord a foreground terminal result when it is verification evidence.r  N)r'  _insert_evidence)r#   r*   r,   r)   r  evidences         r   record_terminal_resultr,  3  sB     -  H tH%%%r   hermes verifyr   )r,   r#   r&   r  
str | Pathokr&   c                   	 ddl m}  ||           }n# t          $ r d}Y nw xY wt          t	          |                                                     }t          |dd|dv r|nd|rdnd	|rdnd
|t          |pi                     d          p|          t          |pd          t          |          
  
        }	t          |	          S )u  Record a completed ``hermes verify`` run as verification evidence.

    Explicit CLI-side write: unlike :func:`record_terminal_result` there is
    nothing to classify — the caller (the ``hermes verify`` command) already
    knows the run was a verification pass and whether it succeeded. A passing
    run marks the workspace ``passed`` for the verify-on-stop guard exactly
    like a passing canonical test command would; a failing run records the
    failure so the guard keeps asking for a fix.

    ``root`` is re-resolved through :func:`agent.coding_context.project_facts_for`
    so the recorded workspace root matches what :func:`verification_status`
    derives when the stop guard later looks the evidence up.
    r   r  Nr-  verify>   r   r   r   r  r  r   r+   r  r  )
r   r  rM   r"   r	   r   r!   r!  r  r*  )
r+   r,   r/  r#   r&   r  r  r"  r   r+  s
             r   record_verify_runr2  I  s   ,::::::!!$''    4::%%''((H#) 444ee&+xx8.!!q%+2""6**6h77z.Y//(00  H H%%%s    ##r+  dict[str, Any]c                f   t                      }t          5  t                      5 }|                    d|| j        | j        | j        | j        | j        | j	        | j
        | j        | j        | j        f          }|j        t          d          t!          |j                  }|                    d| j        | j        |f           t#          || j        | j                   |                                 ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   d|i| j        d|iS )zAInsert a classified evidence row and repoint the workspace state.a  
                INSERT INTO verification_events(
                    created_at, session_id, cwd, root, command, canonical_command,
                    kind, scope, status, exit_code, output_summary
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                Nz.verification event insert did not return an ida  
                INSERT INTO verification_state(
                    session_id, root, last_event_id, last_edit_at, changed_paths_json
                ) VALUES (?, ?, ?, NULL, '[]')
                ON CONFLICT(session_id, root) DO UPDATE SET
                    last_event_id = excluded.last_event_id,
                    last_edit_at = NULL,
                    changed_paths_json = '[]'
                )r,   r+   id
created_at)r6   _DB_LOCKrU   rK   r,   r*   r+   r#   r$   r%   r&   r'   r)   r.   	lastrowidRuntimeErrorr(   r  rY   __dict__)r+  r6  rP   curevent_ids        r   r*  r*  v  s   J	 ' '^^ &	t,, 'LM$.MNO&+ C* }$"#STTT3=))HLL $hmX>   dx/BWWWWKKMMMM&	 &	 &	 &	 &	 &	 &	 &	 &	 &	 &	 &	 &	 &	 &	' ' ' ' ' ' ' ' ' ' ' ' ' ' 'R (Jh/JzJJJs5   DCD6DD	D	D	
DD D)pathsr=  "list[str] | tuple[str, ...] | Nonec                   	 ddl m}  ||          }n# t          $ r d}Y nw xY w|sdS t          | pd          }t          |                    d          p"t          |pd                                                    }t          d |pg D                       }t                      }t          5  t                      5 }	|	                    d||f                                          }
t                      }|
P	 t          t          j        |
d	         pd
                    }n%# t           t"          f$ r t                      }Y nw xY wt          |t          |          z            dd         }|	                    d|||t          j        |          f           |	                                 ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   ||||dS )z>Mark verification evidence stale after a successful file edit.r   r  Nr  r+   r  c                0    h | ]}|t          |          S r   )r"   )r   ps     r   	<setcomp>z(mark_workspace_edited.<locals>.<setcomp>  s#    ???qQ?CFF???r   z
                SELECT changed_paths_json FROM verification_state
                WHERE session_id = ? AND root = ?
                changed_paths_json[]i8a~  
                INSERT INTO verification_state(
                    session_id, root, last_event_id, last_edit_at, changed_paths_json
                ) VALUES (?, ?, NULL, ?, ?)
                ON CONFLICT(session_id, root) DO UPDATE SET
                    last_edit_at = excluded.last_edit_at,
                    changed_paths_json = excluded.changed_paths_json
                )r,   r+   last_edit_atchanged_paths)r   r  rM   r"   r!  r	   r   sortedr6   r7  rU   rK   fetchonesetjsonloads	TypeErrorrp   dumpsrY   )r,   r*   r=  r  r"  sidr+   rF  	edited_atrP   rowexistingmergeds                r   mark_workspace_editedrS    s   ::::::!!#&&    t
j%I
&
&Cuyy  >D$4$4$<$<$>$>??D??U[b???@@M

I	  ^^ 	t,, d  hjj  "%H%"4:c2F.G.O4#P#PQQHH!:. % % %"uuHHH%XM(:(::<<TUUCFLL dItz&'9'9:
 
 
 KKMMM5	 	 	 	 	 	 	 	 	 	 	 	 	 	 	              : tYYfgggsg    ##0G?;F=;)D%$F=%EF=EA*F=1G=G	GG	GGGc                   	 ddl m}  ||          }n# t          $ r d}Y nw xY w|sdddS t          | pd          }t          |                    d          p"t          |pd                                                    }t          5  t                      5 }|	                    d	||f          
                                }| d
d||g dcddd           cddd           S d}|d         /|	                    d|d         f          
                                }ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   g }		 t          j        |d         pd          }	n# t          t          f$ r g }	Y nw xY w|d
d|||	dS t          |          }
|d         r|d         |
d         k    rd}n|
d         }||
|||	dS )zAReturn the best known verification state for a session/workspace.r   r  Nnot_applicable)r'   r+  r  r+   r  z
                SELECT last_event_id, last_edit_at, changed_paths_json
                FROM verification_state
                WHERE session_id = ? AND root = ?
                
unverified)r'   r+  r+   r,   rF  last_event_idz.SELECT * FROM verification_events WHERE id = ?rC  rD  rE  r6  staler'   )r   r  rM   r"   r!  r	   r   r7  rU   rK   rH  rJ  rK  rL  rp   dict)r,   r*   r  r"  rN  r+   rP   stateeventrF  r+  r'   s               r   verification_statusr\    s   ::::::!!#&&    >*===
j%I
&
&Cuyy  >D$4$4$<$<$>$>??D	  ^^ 	tLL
 d  hjj  }* $ "%%' 	 	 	 	 	 	 	       $ E_%1D?+-  (** '	 	 	 	 	 	 	 	 	 	 	 	 	 	 	              2  "M
5)=#>#F$GGz"    }"*
 
 	
 E{{H^ $~!6,9O!O!O(#&  s`    ##
E4D+E&9D+E+D/	/E2D/	3EE	EE- -FF)r0   r"   )r0   r	   )r0   r>   )r0   rR   )rP   r>   r0   rV   )r#   r"   r[   r\   r0   r]   )rz   r]   r|   r(   r)   r(   r0   r\   )r   r"   r0   r"   )r   r"   r0   r   )r   r   r   r   r0   r   )r   r   r0   r   )r   r   r0   r   )r#   r"   r   r   r)   r(   r0   r   )r   r"   r0   r"   )r   r"   r0   r\   )r   r   r0   r"   )r   r"   r0   r\   )r   r"   r+   r   r0   r\   )r   r   r+   r   r0   r   )r   )r#   r"   r+   r   r)   r(   r0   r   )r  r"   r0   r"   )rP   r>   r,   r"   r+   r"   r0   rV   )r#   r"   r*   r   r,   r   r)   r(   r  r"   r0   r  )r#   r"   r*   r   r,   r   r)   r(   r  r"   r0   r(  )r+   r.  r,   r   r/  r\   r#   r"   r&   r"   r  r"   r0   r(  )r+  r!   r0   r3  )r,   r   r*   r   r=  r>  r0   r(  )r,   r   r*   r   r0   r3  )?r/   
__future__r   rJ  rn   rG   r   	threading
contextlibr   dataclassesr   r   r   r   pathlibr	   typingr
   r   r   hermes_constantsr   Lockr7  r	  r9   r  r  r   rX   r   r!   r6   r:   r=   rQ   rU   rL   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r'  r,  r2  r*  rS  r\  r   r   r   <module>re     s    # " " " " "         % % % % % % ! ! ! ! ! ! 2 2 2 2 2 2 2 2 2 2       * * * * * * * * * * , , , , , , 9>   " !' C   $* * * * * * * *
 $       2 2 2 2] ] ] ]: : : :   &    $1 1 1 1h :> F F F F F FRS S S S2         	 	 	 	   .   .   	 	 	 	R R R R      	 	 	 	   *     $
 
 
 
; ; ; ;B "!, , , , , ,j & & & & & &2 ""*& *& *& *& *& *&Z,K ,K ,K ,Kf 15	3h 3h 3h 3h 3h 3hlE E E E E Er   