From ee80dfdea01f748eeebb8daf0e6b9bc0e9900266 Mon Sep 17 00:00:00 2001 From: wysie Date: Wed, 27 May 2026 19:43:14 +0800 Subject: [PATCH] fix: preserve skill packages during curator consolidation --- agent/curator.py | 21 ++++++++++++++++++++- tests/agent/test_curator.py | 15 +++++++++++++++ website/docs/user-guide/features/curator.md | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/agent/curator.py b/agent/curator.py index d0147d4c4fb..e7e5952811d 100644 --- a/agent/curator.py +++ b/agent/curator.py @@ -390,7 +390,26 @@ CURATOR_REVIEW_PROMPT = ( "(verification scripts, fixture generators, probes)\n" " Then archive the old sibling. Use `terminal` with `mkdir -p " "~/.hermes/skills//references/ && mv ... /" - "references/.md` (or templates/ / scripts/).\n" + "references/.md` (or templates/ / scripts/).\n\n" + "Package integrity — not optional:\n" + "Before demoting or archiving a skill, inspect it as a COMPLETE " + "directory package, not just SKILL.md. A skill root may include " + "`references/`, `templates/`, `scripts/`, and `assets/`; `skill_view` " + "discovers those relative to the skill root. A reference markdown file " + "inside another skill is NOT a new skill root and does not get its own " + "linked-file discovery.\n" + "If the source skill has support files OR SKILL.md contains relative " + "links such as `references/...`, `templates/...`, `scripts/...`, or " + "`assets/...`, DO NOT flatten only SKILL.md into " + "`/references/.md`. Choose one safe path instead:\n" + " • keep it as a standalone skill, OR\n" + " • fully merge it by re-homing every needed support file into the " + "umbrella's canonical `references/`, `templates/`, `scripts/`, or " + "`assets/` directories AND rewrite the destination instructions to " + "the new paths, OR\n" + " • archive the entire original skill package unchanged.\n" + "Never leave archived/demoted instructions pointing at files that were " + "left behind under the old skill directory.\n" "4. Also flag skills whose NAME is too narrow (contains a PR number, " "a feature codename, a specific error string, an 'audit' / " "'diagnosis' / 'salvage' session artifact). These almost always " diff --git a/tests/agent/test_curator.py b/tests/agent/test_curator.py index 69dc5f85786..b564d9f9a08 100644 --- a/tests/agent/test_curator.py +++ b/tests/agent/test_curator.py @@ -592,6 +592,21 @@ def test_curator_review_prompt_is_umbrella_first(): ) +def test_curator_review_prompt_preserves_skill_package_integrity(): + """Consolidation must not flatten package skills and break linked files.""" + from agent.curator import CURATOR_REVIEW_PROMPT + + lower = CURATOR_REVIEW_PROMPT.lower() + assert "complete" in lower and "directory package" in lower + assert "not a new skill root" in lower + assert "do not flatten only skill.md" in lower + assert "rewrite" in lower and "new paths" in lower + assert "archive the entire original skill package unchanged" in lower + for dirname in ("references/", "templates/", "scripts/", "assets/"): + assert dirname in CURATOR_REVIEW_PROMPT + + + def test_curator_review_prompt_offers_support_file_actions(): """Support-file demotion (references/templates/scripts) must be one of the three consolidation methods, alongside merge-into-existing and diff --git a/website/docs/user-guide/features/curator.md b/website/docs/user-guide/features/curator.md index 1d5739e5163..56ec4046f68 100644 --- a/website/docs/user-guide/features/curator.md +++ b/website/docs/user-guide/features/curator.md @@ -32,7 +32,7 @@ If you want to see what the curator *would* do before it runs for real, run `her A run has two phases: 1. **Automatic transitions** (deterministic, no LLM). Skills unused for `stale_after_days` (30) become `stale`; skills unused for `archive_after_days` (90) are moved to `~/.hermes/skills/.archive/`. -2. **LLM review** (single aux-model pass, `max_iterations=8`). The forked agent surveys the agent-created skills, can read any of them with `skill_view`, and decides per-skill whether to keep, patch (via `skill_manage`), consolidate overlapping ones, or archive via the terminal tool. +2. **LLM review** (single aux-model pass, `max_iterations=8`). The forked agent surveys the agent-created skills, can read any of them with `skill_view`, and decides per-skill whether to keep, patch (via `skill_manage`), consolidate overlapping ones, or archive via the terminal tool. Consolidation treats a skill as a full package: if a skill has `references/`, `templates/`, `scripts/`, `assets/`, or relative links to those paths, the curator must either keep it standalone, re-home the needed support files and rewrite paths, or archive the entire package unchanged — not flatten only `SKILL.md` into another skill's `references/` file. Pinned skills are off-limits to both the curator's auto-transitions and the agent's own `skill_manage` tool. See [Pinning a skill](#pinning-a-skill) below.