mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-06 02:41:48 +00:00
Tighten the provenance semantics added in #19618: skills a user asks a foreground agent to write via skill_manage(create) now stay invisible to the curator. Only skills the background self-improvement review fork sediments through skill_manage get the created_by=agent marker. - tools/skill_provenance.py — new ContextVar module mirroring the _approval_session_key pattern: set_current_write_origin / reset / get / is_background_review. Default origin is 'foreground'; the review fork sets 'background_review'. - run_agent.py — run_conversation() binds the ContextVar from self._memory_write_origin at the top of each call. The review fork runs on its own thread (fresh context), so foreground and review contexts never cross-contaminate. - tools/skill_manager_tool.py — skill_manage(action='create') now only calls mark_agent_created() when is_background_review(). All other cases (foreground create, patch, edit, write_file, delete) continue as before. - tests: test_skill_provenance.py (6 tests covering the ContextVar surface), split test_full_create_via_dispatcher into foreground vs. review-fork variants, curator status tests now mark-first. Why: the agent routinely edits existing user skills on the user's behalf; those writes must never flip provenance. And when a user explicitly asks the foreground agent to create a skill, that skill belongs to the user. The curator should only be cleaning up after its own autonomous sediment from the review nudge loop.
102 lines
3 KiB
Python
102 lines
3 KiB
Python
"""Tests for tools/skill_provenance.py — write-origin ContextVar."""
|
|
|
|
import contextvars
|
|
|
|
import pytest
|
|
|
|
|
|
def test_default_origin_is_foreground():
|
|
from tools.skill_provenance import get_current_write_origin
|
|
# In a fresh ContextVar context, default kicks in.
|
|
ctx = contextvars.copy_context()
|
|
origin = ctx.run(get_current_write_origin)
|
|
assert origin == "foreground"
|
|
|
|
|
|
def test_set_and_get_origin():
|
|
from tools.skill_provenance import (
|
|
set_current_write_origin,
|
|
reset_current_write_origin,
|
|
get_current_write_origin,
|
|
)
|
|
token = set_current_write_origin("background_review")
|
|
try:
|
|
assert get_current_write_origin() == "background_review"
|
|
finally:
|
|
reset_current_write_origin(token)
|
|
|
|
|
|
def test_reset_restores_prior_origin():
|
|
from tools.skill_provenance import (
|
|
set_current_write_origin,
|
|
reset_current_write_origin,
|
|
get_current_write_origin,
|
|
)
|
|
outer = set_current_write_origin("assistant_tool")
|
|
try:
|
|
inner = set_current_write_origin("background_review")
|
|
try:
|
|
assert get_current_write_origin() == "background_review"
|
|
finally:
|
|
reset_current_write_origin(inner)
|
|
assert get_current_write_origin() == "assistant_tool"
|
|
finally:
|
|
reset_current_write_origin(outer)
|
|
|
|
|
|
def test_is_background_review_truthy_only_for_review():
|
|
from tools.skill_provenance import (
|
|
set_current_write_origin,
|
|
reset_current_write_origin,
|
|
is_background_review,
|
|
BACKGROUND_REVIEW,
|
|
)
|
|
for origin, expected in (
|
|
("foreground", False),
|
|
("assistant_tool", False),
|
|
("random_other_value", False),
|
|
(BACKGROUND_REVIEW, True),
|
|
):
|
|
token = set_current_write_origin(origin)
|
|
try:
|
|
assert is_background_review() is expected, (
|
|
f"is_background_review() wrong for origin={origin!r}"
|
|
)
|
|
finally:
|
|
reset_current_write_origin(token)
|
|
|
|
|
|
def test_empty_origin_falls_back_to_foreground():
|
|
from tools.skill_provenance import (
|
|
set_current_write_origin,
|
|
reset_current_write_origin,
|
|
get_current_write_origin,
|
|
)
|
|
token = set_current_write_origin("")
|
|
try:
|
|
# Empty is coerced to "foreground" at the set() boundary.
|
|
assert get_current_write_origin() == "foreground"
|
|
finally:
|
|
reset_current_write_origin(token)
|
|
|
|
|
|
def test_context_isolation_between_copies():
|
|
"""ContextVar scoping: modifications in one copy do not leak out."""
|
|
from tools.skill_provenance import (
|
|
set_current_write_origin,
|
|
get_current_write_origin,
|
|
BACKGROUND_REVIEW,
|
|
)
|
|
|
|
# Start at the module default.
|
|
original = get_current_write_origin()
|
|
|
|
def _run_in_copy():
|
|
set_current_write_origin(BACKGROUND_REVIEW)
|
|
return get_current_write_origin()
|
|
|
|
ctx = contextvars.copy_context()
|
|
inside = ctx.run(_run_in_copy)
|
|
assert inside == BACKGROUND_REVIEW
|
|
# Parent context unaffected.
|
|
assert get_current_write_origin() == original
|