mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-06 10:47:12 +08: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.
103 lines
3.0 KiB
Python
103 lines
3.0 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
|