From 62364122946e961e638226d8f5c9a0ce2e8f1da0 Mon Sep 17 00:00:00 2001 From: 19404 <1940428933@qq.com> Date: Sat, 18 Jul 2026 06:53:06 +0800 Subject: [PATCH] fix(curator): guard background review writes against manually authored skills MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevents the curator's LLM consolidation pass from archiving skills the user placed manually (e.g. via URL install, direct SKILL.md authoring, or Gitee source). These skills carry created_by=None in .usage.json rather than created_by=agent, but the _background_review_write_guard only checked pinned, external, bundled, hub, and protected built-in status — missing the manual-skill case entirely. The guard already caught a real case: the user's 'auto-dev' skill (use_count=50, patch_count=119) was archived 28 seconds after its last use during a curator auto-run. Adds a check: if the skill has a usage record and its created_by is not 'agent', refuse the background curator write. Skills with no record at all (new/unknown) are not blocked. --- tools/skill_manager_tool.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/skill_manager_tool.py b/tools/skill_manager_tool.py index eaf30dd41a..debea52642 100644 --- a/tools/skill_manager_tool.py +++ b/tools/skill_manager_tool.py @@ -374,6 +374,23 @@ def _background_review_write_guard( f"skill '{name}'." ), } + # Manually authored skills (created_by != "agent") are off-limits + # to autonomous curation. This prevents the LLM consolidation pass + # from archiving skills the user placed manually (e.g. via URL + # install or direct SKILL.md authoring), which lack the + # `created_by: "agent"` marker. + usage_data = skill_usage.load_usage() + usage_rec = usage_data.get(name) + if isinstance(usage_rec, dict) and not skill_usage._is_curator_managed_record(usage_rec): + return { + "success": False, + "error": ( + f"Refusing background curator {action} for skill " + f"'{name}': the skill records show it is not agent-created " + f"(created_by={usage_rec.get('created_by')!r}). Manually authored " + f"skills are off-limits to autonomous curation." + ), + } except Exception: logger.debug("owned skill guard lookup failed for %s", name, exc_info=True) return None