mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-02 12:13:05 +00:00
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.
53 lines
1.8 KiB
Python
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
|