hermes-agent/tests/agent/test_verify_hooks.py
Brooklyn Nicholson a10113658b feat(agent): add pre_verify hook and verify-on-stop coding guidance
Add a `pre_verify` user/plugin/shell hook fired once per turn when the agent
edited code and is about to finish, after the existing verify-on-stop guard. A
hook can keep the agent going one more turn (run a check, defer it, tidy the
diff) by returning {"action":"continue","message":...} (the Claude-Code Stop
shape {"decision":"block","reason":...} is accepted too). Hooks receive coding,
attempt, final_response, and sorted changed_paths so they can self-scope and
self-throttle; the path is bounded by agent.max_verify_nudges and preserves
message-role alternation.

Hermes still ships its default coding guidance (agent.verify_guidance, on by
default), but it now rides the evidence-based verify-on-stop missing-evidence
nudge instead of a separate default pre_verify continuation, so it costs no
extra model turn of its own. Guidance reuses the shared utils.is_truthy_value
parser rather than a local copy.
2026-06-30 00:59:29 -05:00

53 lines
1.8 KiB
Python

"""Unit tests for the verification-loop policy (agent/verify_hooks.py).
The `pre_verify` user-hook aggregation lives in `hermes_cli.plugins`
(`get_pre_verify_continue_message`) and is tested in
`tests/hermes_cli/test_plugins.py`, alongside `get_pre_tool_call_block_message`.
"""
from __future__ import annotations
from agent import verify_hooks
class TestMaxVerifyNudges:
def test_default_when_unset(self):
assert (
verify_hooks.max_verify_nudges({})
== verify_hooks.DEFAULT_MAX_VERIFY_NUDGES
)
assert (
verify_hooks.max_verify_nudges({"agent": {}})
== verify_hooks.DEFAULT_MAX_VERIFY_NUDGES
)
def test_reads_and_coerces(self):
assert verify_hooks.max_verify_nudges({"agent": {"max_verify_nudges": 5}}) == 5
assert verify_hooks.max_verify_nudges({"agent": {"max_verify_nudges": "2"}}) == 2
assert verify_hooks.max_verify_nudges({"agent": {"max_verify_nudges": -1}}) == 0
def test_bad_value_falls_back(self):
assert (
verify_hooks.max_verify_nudges({"agent": {"max_verify_nudges": "x"}})
== verify_hooks.DEFAULT_MAX_VERIFY_NUDGES
)
class TestCodingVerifyGuidance:
def test_enabled_by_default(self):
assert (
verify_hooks.coding_verify_guidance({})
== verify_hooks.CODING_VERIFY_GUIDANCE
)
assert (
verify_hooks.coding_verify_guidance({"agent": {}})
== verify_hooks.CODING_VERIFY_GUIDANCE
)
def test_reads_truthy_config(self):
cfg = {"agent": {"verify_guidance": "yes"}}
assert verify_hooks.coding_verify_guidance(cfg) == verify_hooks.CODING_VERIFY_GUIDANCE
def test_opt_out_via_config(self):
off = {"agent": {"verify_guidance": False}}
assert verify_hooks.coding_verify_guidance(off) is None