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.
This commit is contained in:
Teknium
2026-04-26 06:08:39 -07:00
committed by Teknium
parent 88602376d4
commit bc79e227e6
12 changed files with 1987 additions and 4 deletions

View File

@@ -2382,6 +2382,30 @@ class GatewayRunner:
# Discover and load event hooks
self.hooks.discover_and_load()
# Curator — kick off a background skill-maintenance pass on gateway
# startup if the schedule says we're due. Runs in a daemon thread
# so it never blocks gateway startup. Best-effort; any failure is
# swallowed. The interval_hours gate prevents re-running on quick
# restarts.
try:
from agent.curator import maybe_run_curator
def _curator_summary(msg: str) -> None:
# Surface the one-line summary into gateway logs so operators
# can see what the curator did. No per-platform push since
# there's no user-facing session at gateway boot.
logger.info("curator: %s", msg)
maybe_run_curator(
idle_for_seconds=float("inf"), # gateway boot = no active agent
on_summary=_curator_summary,
)
except Exception:
logger.debug(
"curator boot hook failed", exc_info=True,
)
# Recover background processes from checkpoint (crash recovery)
try: