
    `gj`,                        d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 dZ
 eh d      Z eh d      Zdd	Zdd
Z eh d      ZddZdddZddZ	 	 	 	 	 	 ddZddZddZddd	 	 	 	 	 	 	 	 	 d dZddgZy)!a  Turn-end verification guard for coding edits.

This module is intentionally policy-only. It never runs checks itself; it turns
the passive verification ledger into a bounded follow-up when the model tries to
finish immediately after editing code without fresh evidence.
    )annotationsN)Path)AnyIterable   >   .md.csv.log.mdx.org.rst.tsv.txt.adoc.text	.asciidoc	.markdown>   noticeauthorslicencelicense	changelog
codeownerscontributorsc                    	 t        t        |             }|j                  j	                         }|t
        v ry|s!|j                  j	                         t        v ryy# t        $ r Y yw xY w)zNReturn True when a changed path is documentation/prose with nothing to verify.FT)r   str	Exceptionsuffixlower_NON_CODE_VERIFY_EXTENSIONSname_NON_CODE_VERIFY_FILENAMES)rawpr   s      J/root/.hermes/venv/lib/python3.12/site-packages/agent/verification_stop.py_is_non_code_pathr&   8   sa    SN XX^^F,,afflln(BB  s   A 	A)(A)c                J    | D cg c]  }|st        |      r| c}S c c}w )zODrop documentation/prose paths; keep paths that could have verifiable behavior.)r&   )pathsr$   s     r%   _filter_verifiable_pathsr)   F   s     ?!*;A*>A???s      >    clituitoolcodexlocaldesktopgatewaywebhook
api_servermsgraph_webhookc                    	 ddl m}  t        j                  d      xs	  | dd      } | dd      }||fD ]:  }t        |xs d      j                         j                         }|s1|t        vs: y y# t        $ r[ t        j                  dd      xs  t        j
                  j                  dd      }t        j
                  j                  dd      }Y w xY w)	ai  Return whether this turn is delivered over a human messaging channel.

    The gateway binds the platform value (e.g. ``telegram``) to
    ``HERMES_SESSION_PLATFORM``; the CLI and TUI set ``HERMES_SESSION_SOURCE``
    (e.g. ``cli``, ``tui``) instead. Both are consulted via the session-context
    helper (with an ``os.environ`` fallback), alongside the ``HERMES_PLATFORM``
    override, matching the sibling platform resolution in
    ``agent/skill_commands.py`` and ``agent/prompt_builder.py``. A turn is a
    messaging surface when a resolved identity is present and is not a known
    non-messaging surface.
    r   )get_session_envHERMES_PLATFORMHERMES_SESSION_PLATFORMr*   HERMES_SESSION_SOURCETF)gateway.session_contextr6   osgetenvr   environgetr   stripr   _NON_MESSAGING_SESSION_SURFACES)r6   platformsourceidentitys       r%   _session_is_messaging_surfacerD   g   s    =; II'( >8"= 	 !!8"= v& x~2&,,.446(GG   =99.3 
rzz~~%r8
  7<	=s   /A3 3A!CCc                $   t         j                  j                  d      }| |j                         j	                         dvS | 	 ddlm}  |       } t        | t              r| xs i j                  d      nd}t        |t              r|j                  d      nd}t        |t              r|S t        |t              r8|j                         j	                         }|dv ry	|dv ry
|dk(  rt                S t                S # t        $ r i } Y w xY w)u  Return whether edit -> verify-before-finish behavior is enabled.

    Precedence: an explicit ``HERMES_VERIFY_ON_STOP`` env var wins, then an
    explicit ``agent.verify_on_stop`` config value. The config default is
    ``"auto"`` (see ``DEFAULT_CONFIG``) — surface-aware: ON for interactive
    coding surfaces (CLI, TUI, desktop) and programmatic callers, OFF for
    conversational messaging surfaces (Telegram, Discord, etc.) where the
    verification narrative would reach a human as chat noise. An explicit
    bool forces the behavior in either direction. A missing or unrecognized
    value falls back to the surface-aware ``"auto"`` default.
    HERMES_VERIFY_ON_STOPN>   0noofffalser   )load_configagentverify_on_stop>   1onyestrueTFauto)r;   r=   r>   r?   r   hermes_cli.configrK   r   
isinstancedictboolr   rD   )configenvrK   	agent_cfgcfg_valtokens         r%   verify_on_stop_enabledr\      s    **..0
1C
yy{  "*EEE~	5 ]F 0:&$/G2""7+TI1;It1Limm,-RVG'4 '3%%'..//F?4666,...  	F	s   D DDc                R   g }t               }| D ]  }|s	 t        |      j                         }|j                         r|n|j                  }t        |j                               }||vs\|j                  |       |j                  t        |              |S # t        $ r Y w xY wN)
setr   
expanduseris_dirparentr   resolver   addappend)r(   
candidatesseenr#   path	candidateresolveds          r%   _candidate_cwdsrk      s    JUD .	9'')D $4;;I9,,./H 4HHXd8n-.   		s   AB	B&%B&c                    	 ddl m} ddlm} d}t        |      D ]D  } ||      }|s || |      }||f}||}t        |j                  d      xs d      dk7  sB|c S  |S # t        $ r Y yw xY w)	zHReturn ``(status, facts)`` for the first edited workspace needing proof.r   )project_facts_for)verification_statusN)
session_idcwdstatus
unverifiedpassed)agent.coding_contextrm   agent.verification_evidencern   r   rk   r   r>   )	ro   changed_pathsrm   rn   first_snapshotrp   factsrq   snapshots	            r%   _verification_snapshotrz      s    :C DHN}- 	!#&$
DE?!%Nvzz(#3|4@O	   s   A$ $	A0/A0c                    | d t          }|D cg c]  }d| d
 }}t        |       t        |      z
  }|dkD  r|j                  d| d       dj                  |      S c c}w )Nz- ``r   z
- ... and z more
)_MAX_CHANGED_PATHS_IN_NUDGElenre   join)r(   shownrh   lines	remainings        r%   _format_changed_pathsr      sm    ../E',-ts4&]-E-E
SZ'I1}z)E2399U	 .s   Ac                   t        | j                  d      xs d      }t        | j                  d      t              r| j                  d      nd }|s|S |j                  d      xs |j                  d      }t        |j                  d      xs d      j	                         }|g}|r|j                  d| d	       |r:d
}t        |      |kD  r|d | j                         dz   }|j                  d|        dj                  |      S )Nrq   rr   evidencecanonical_commandcommandoutput_summaryr*   zlast command `r|   i  z
... [truncated]zlast output:
r}   )	r   r>   rT   rU   r?   re   r   rstripr   )rq   stater   r   summarypartsmax_summarys          r%   _status_detailr      s    

8$45E)3FJJz4JD)Qvzz*%W[Hll./J8<<	3JG(,,/06B7==?GGE~gYa01w<+%l{+2247JJG~gY/099U       )attemptsmax_attemptsc           	         t        t        |      D ch c]  }t        |       c}      }|r||k\  ryt        | |      }|y|\  }}|j	                  d      xs g D 	cg c]4  }	t        |	      j                         rt        |	      j                         6 }
}	t        |j	                  d      xs d      }|dk(  ry	 ddlm}  |       }|rd	| nd
}|
r5ddj                  d |
dd D              z   t        |
      dkD  rdnd
z   dz   }n7t        j                  j                  t        j                               }d| d}dt!        |       dt#        |       d	| d| d	S c c}w c c}	w # t        $ r d}Y w xY w)zGReturn a synthetic follow-up when edited code lacks fresh verification.N)ro   rv   verifyCommandsrq   rr   rs   r   )coding_verify_guidancez

r*   z+Run the relevant verification command now (z, c              3  (   K   | ]
  }d | d   yw)r|   N ).0cmds     r%   	<genexpr>z-build_verify_on_stop_nudge.<locals>.<genexpr>  s     Bs!C5
Bs      z, ...z@), read any failure, repair the code, and summarize what passed.ziNo canonical test/lint/build command was detected. Create a focused temporary verification script under `z` using an OS-safe `tempfile` path with a `hermes-verify-` filename prefix, run it against the changed behavior, clean it up when possible, and summarize it explicitly as ad-hoc verification rather than suite green.z[System: You edited code in this turn, but the workspace does not have fresh passing verification evidence yet.

Verification status: z

Changed paths:
zn If verification is not possible, explain the concrete blocker instead of claiming the work is fully verified.])sortedr)   r   rz   r>   r?   agent.verify_hooksr   r   r   r   r;   rh   realpathtempfile
gettempdirr   r   )ro   rv   r   r   r$   r(   ry   rq   rx   r   verify_commandsr   r   guidanceaddendumcommand_instructiontemp_dirs                    r%   build_verify_on_stop_nudger      s    $<]$KLqCFLMEH,%5QHMFE II./52s8>> 	CO  

8$45E=)+ %-hZ "H9iiBobq.ABBCo.2w< QQ 	 77##H$7$7$9:44<: > 		  .v 67 8078
  K*A	] M  s   E% 9E* E/ /E=<E=r   r\   )r#   r   returnrV   )r(   Iterable[str]r   	list[str])r   rV   r^   )rW   zdict[str, Any] | Noner   rV   )r(   r   r   z
list[Path])ro   
str | Nonerv   r   r   z,tuple[dict[str, Any], dict[str, Any]] | None)r(   r   r   r   )rq   zdict[str, Any]r   r   )
ro   r   rv   r   r   intr   r   r   r   )__doc__
__future__r   r;   r   pathlibr   typingr   r   r~   	frozensetr    r"   r&   r)   r@   rD   r\   rk   rz   r   r   r   __all__r   r   r%   <module>r      s    # 	        ( & '
 @  #,# "@#/L$  2	4. AA !A 	A
 A AH ()A
Br   