hermes-bsd/tools
Teknium bc79e227e6 feat(curator): background skill maintenance (issue #7816)
Adds the Curator — an auxiliary-model background task that periodically
reviews AGENT-CREATED skills and keeps the collection tidy: tracks usage,
transitions unused skills through active → stale → archived, and spawns
a forked AIAgent to consolidate overlaps and patch drift.

Default: enabled, inactivity-triggered (no cron daemon). Runs on CLI
startup and gateway boot when the last run is older than interval_hours
(default 24) AND the agent has been idle for min_idle_hours (default 2).

Invariants (all load-bearing):
- Never touches bundled or hub-installed skills (.bundled_manifest +
  .hub/lock.json double-filter)
- Never auto-deletes — archive only. Archives are recoverable
  via `hermes curator restore <skill>`
- Pinned skills bypass all auto-transitions
- Uses the aux client; never touches the main session's prompt cache

New files:
- tools/skill_usage.py — sidecar .usage.json telemetry, atomic writes,
  provenance filter
- agent/curator.py — orchestrator: config, idle gating, state-machine
  transitions (pure, no LLM), forked-agent review prompt
- hermes_cli/curator.py — `hermes curator {status,run,pause,resume,
  pin,unpin,restore}` subcommand
- tests/tools/test_skill_usage.py — 29 tests
- tests/agent/test_curator.py — 25 tests

Modified files (surgical patches):
- tools/skills_tool.py — bump view_count on successful skill_view
- tools/skill_manager_tool.py — bump patch_count on skill_manage
  patch/edit/write_file/remove_file; forget record on delete
- hermes_cli/config.py — add curator: section to DEFAULT_CONFIG
- hermes_cli/commands.py — add /curator CommandDef with subcommands
- hermes_cli/main.py — register `hermes curator` subparser via
  register_cli() from hermes_cli.curator
- cli.py — /curator slash-command dispatch + startup hook
- gateway/run.py — gateway-boot hook (mirrors CLI)

Validation:
- 54 new tests across skill_usage + curator, all passing in 3s
- 346 tests across all touched files' neighbors green
- 2783 tests across hermes_cli/ + gateway/test_run_progress_topics.py green
- CLI smoke: `hermes curator status/pause/resume` work end-to-end

Companion to PR #16026 (class-first skill review prompt) — together
they form a loop: the review prompt stops near-duplicate skill creation
at the source, and the curator prunes/consolidates what still accumulates.

Refs #7816.
2026-04-28 22:33:33 -07:00
..
browser_providers
environments fix(gateway,terminal): expand shell tilde in terminal.cwd before subprocess 2026-04-28 22:26:09 -07:00
neutts_samples
__init__.py
ansi_strip.py
approval.py perf(approval): precompile DANGEROUS_PATTERNS and HARDLINE_PATTERNS (#17206) 2026-04-28 18:44:14 -07:00
binary_extensions.py
browser_camofox.py
browser_camofox_state.py
browser_cdp_tool.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
browser_dialog_tool.py feat(browser): CDP supervisor — dialog detection + response + cross-origin iframe eval (#14540) 2026-04-23 22:23:37 -07:00
browser_supervisor.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
browser_tool.py fix(browser): detect missing Chromium and fail fast with actionable error (#17039) 2026-04-28 07:03:44 -07:00
budget_config.py
checkpoint_manager.py feat(checkpoints): auto-prune orphan and stale shadow repos at startup (#16303) 2026-04-26 19:05:52 -07:00
clarify_tool.py
code_execution_tool.py feat(terminal): collapse subagent task_ids to shared container (#16177) 2026-04-26 11:55:02 -07:00
credential_files.py
cronjob_tools.py fix(cron): wire context_from through the update action 2026-04-25 04:49:28 -07:00
debug_helpers.py
delegate_tool.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
discord_tool.py fix(discord_tool): coerce limit parameter to int before min() call 2026-04-26 20:48:38 -07:00
env_passthrough.py
feishu_doc_tool.py
feishu_drive_tool.py
file_operations.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
file_state.py
file_tools.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
fuzzy_match.py
homeassistant_tool.py
image_generation_tool.py
interrupt.py
managed_tool_gateway.py
mcp_oauth.py fix(mcp-oauth): preserve server_url path for protected-resource validation (#16031) 2026-04-26 05:43:54 -07:00
mcp_oauth_manager.py fix(mcp-oauth): preserve server_url path for protected-resource validation (#16031) 2026-04-26 05:43:54 -07:00
mcp_tool.py refactor(schema): consolidate nullable-union stripping in schema_sanitizer 2026-04-28 04:58:03 -07:00
memory_tool.py refactor: consolidate symlink-safe atomic replace into shared helper 2026-04-28 04:58:22 -07:00
mixture_of_agents_tool.py Fix (mixture_of_agents): replace deprecated Gemini model and forward max_tokens to OpenRouter (#6621) 2026-04-23 15:14:11 -07:00
neutts_synth.py
openrouter_client.py
osv_check.py
patch_parser.py
path_security.py
process_registry.py chore: extend [SYSTEM:→[IMPORTANT: rename + AUTHOR_MAP 2026-04-26 08:44:58 -07:00
registry.py perf(tools): memoize get_tool_definitions + TTL-cache check_fn results (#17098) 2026-04-28 18:20:17 -07:00
rl_training_tool.py
schema_sanitizer.py refactor(schema): consolidate nullable-union stripping in schema_sanitizer 2026-04-28 04:58:03 -07:00
send_message_tool.py fix(email): add required Date header to outbound mail 2026-04-27 06:41:11 -07:00
session_search_tool.py fix(session-search): exclude current lineage root deterministically in recent mode 2026-04-26 19:03:17 -07:00
skill_manager_tool.py feat(curator): background skill maintenance (issue #7816) 2026-04-28 22:33:33 -07:00
skill_usage.py feat(curator): background skill maintenance (issue #7816) 2026-04-28 22:33:33 -07:00
skills_guard.py
skills_hub.py feat(skills): install skills from a direct HTTP(S) URL (#16323) 2026-04-26 20:57:10 -07:00
skills_sync.py refactor: consolidate symlink-safe atomic replace into shared helper 2026-04-28 04:58:22 -07:00
skills_tool.py feat(curator): background skill maintenance (issue #7816) 2026-04-28 22:33:33 -07:00
terminal_tool.py fix(gateway,terminal): expand shell tilde in terminal.cwd before subprocess 2026-04-28 22:26:09 -07:00
tirith_security.py
todo_tool.py
tool_backend_helpers.py fix(cli): coerce use_gateway config flags in tool routing 2026-04-26 19:02:55 -07:00
tool_output_limits.py feat(skills): add design-md skill for Google's DESIGN.md spec (#14876) 2026-04-23 21:51:19 -07:00
tool_result_storage.py
transcription_tools.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00
tts_tool.py
url_safety.py fix(security): treat quoted false as false in browser SSRF guards 2026-04-26 18:27:13 -07:00
vision_tools.py feat(image-input): native multimodal routing based on model vision capability (#16506) 2026-04-27 06:27:59 -07:00
voice_mode.py
web_tools.py perf(tools): memoize get_tool_definitions + TTL-cache check_fn results (#17098) 2026-04-28 18:20:17 -07:00
website_policy.py
xai_http.py
yuanbao_tools.py chore: remove unused imports and dead locals (ruff F401, F841) (#17010) 2026-04-28 06:46:45 -07:00