You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(skills): delete a skill only when the user asks for it (#536)
The tool described delete as "delete skills you created", which the code never
enforced and which does not fit how skills are made: most are written by the
user and the agent together, so who made the first call says nothing about
whether anyone minds the skill going. With the post-turn review gone there is
no case left for the agent deleting unasked, so the rule is simply: delete an
attached skill only when the user asks, whoever wrote it. Stated in the tool
description, the delete schema, and the manage-skills guidance (1.3; 1.2's
fingerprint recorded). No code gate: the request lives in the conversation, so
only the model can attest it either way.
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,7 +129,7 @@ August 2026; recover it from git history if useful, but do not trust it.)
129
129
-`Agents/Skills/` — skill `<name>/SKILL.md` dirs. **Everything is a skill**: the 4 former capabilities (`vault`, `notes`, `web`, `update`) ship as bundled **core skills** whose body is their guidance and whose `allowed-tools` frontmatter attaches built-in tools; user skills are the same thing with no attached tools. Discovery scans this folder and treats every `SKILL.md` dir as a skill (no reserved names, no `GUIDANCE.md`).
130
130
-`Agents/<Agent Name>/AGENT.md` — one folder per agent, holding its definition note. The note's **body IS the system prompt**: base instructions, the `# Current Date` section, and the `# Memory` section, all in one editable place. There is no memory toggle — an agent participates in memory iff its note still has that section, which the user can simply delete. The folder is the unit rename/duplicate/delete operate on (see `PromptFilesService`).
131
131
The whole tree is plugin machinery, excluded from indexing/search/graph via `isAgentFilePath` in `utils/fileFiltering.ts` (path helpers in `utils/agentPaths.ts`). One deliberate exemption: `list_directory` always shows `Agents/Memories/` — memory notes are absent from the search index, so that listing is the agent's only memory-discovery path (the default `# Memory` section directs it there). Legacy installs are consolidated on first run (`SkillsService.migrateAgentFolder`, from the old top-level `Skills/` folder or the pre-vault `<configDir>/skills`); the v6 `migrateCoreSkills` deletes orphaned per-core-skill `GUIDANCE.md` files so the bundled core-skill `SKILL.md`s seed cleanly into the same dirs.
132
-
- `src/skills/` — Two-phase skill system (Agent Skills style): discover frontmatter on startup, load full content on demand. Bundled defaults under `src/skills/defaults/` (including the `vault`/`notes`/`web`/`manage-skills` core skills — the last one was named `update-skills` before it gained create/delete, migrated in schema v8). **`allowed-tools` is load-bearing**: `AgentManager.buildToolsForAgent` binds a built-in tool only when some *enabled* skill attaches it via `allowed-tools` AND the per-tool `toolsConfig[toolId].enabled` override hasn't vetoed it. All skill guidance reaches the model lazily — advertised by description in the `# Skills` `<available_skills>` block, body loaded on demand via `load_skill`; a skill whose declared built-in tools are *all* vetoed by per-tool overrides is hidden from both surfaces (`AgentManager.skillHasUsableTools`), so the model is never taught a tool that won't be bound. The `manage_skills` tool (the "Manage Skills" core skill, on by default since schema v14; the Tools modal turns it off) lets an agent create new skills, revise its own attached skills, or delete skills it created; unlike `manage_notes`, every operation applies immediately with no `pendingChangesStore` review step — creating a skill is the same action as attaching it. A created skill gets no explicit `agent.skills` entry, so it reads as attached (`?? true`) the moment its file exists on disk. `allowedTools` on a new skill is filtered through a fixed read-only allow-list, never passed through verbatim — the one guard against an agent granting itself new capability via a skill it just wrote. Deleting a built-in core skill is refused (it would just reappear via `bootstrapDefaultSkills` on next startup). Because a tool can be attached by more than one skill (e.g. an integration skill re-declaring a tool a core skill already owns), per-tool overrides are **not** configured per-skill — they live in one agent-level `ToolsModal` (opened from the "Tools" row in the Agent editor's General section), which lists all `BUILT_IN_TOOL_IDS` flat and shows each tool's attaching skill(s).
132
+
- `src/skills/` — Two-phase skill system (Agent Skills style): discover frontmatter on startup, load full content on demand. Bundled defaults under `src/skills/defaults/` (including the `vault`/`notes`/`web`/`manage-skills` core skills — the last one was named `update-skills` before it gained create/delete, migrated in schema v8). **`allowed-tools` is load-bearing**: `AgentManager.buildToolsForAgent` binds a built-in tool only when some *enabled* skill attaches it via `allowed-tools` AND the per-tool `toolsConfig[toolId].enabled` override hasn't vetoed it. All skill guidance reaches the model lazily — advertised by description in the `# Skills` `<available_skills>` block, body loaded on demand via `load_skill`; a skill whose declared built-in tools are *all* vetoed by per-tool overrides is hidden from both surfaces (`AgentManager.skillHasUsableTools`), so the model is never taught a tool that won't be bound. The `manage_skills` tool (the "Manage Skills" core skill, on by default since schema v14; the Tools modal turns it off) lets an agent create new skills, revise its own attached skills, or delete a skill the user asked it to delete (whoever wrote it; the rule is guidance, since only the conversation holds the request); unlike `manage_notes`, every operation applies immediately with no `pendingChangesStore` review step — creating a skill is the same action as attaching it. A created skill gets no explicit `agent.skills` entry, so it reads as attached (`?? true`) the moment its file exists on disk. `allowedTools` on a new skill is filtered through a fixed read-only allow-list, never passed through verbatim — the one guard against an agent granting itself new capability via a skill it just wrote. Deleting a built-in core skill is refused (it would just reappear via `bootstrapDefaultSkills` on next startup). Because a tool can be attached by more than one skill (e.g. an integration skill re-declaring a tool a core skill already owns), per-tool overrides are **not** configured per-skill — they live in one agent-level `ToolsModal` (opened from the "Tools" row in the Agent editor's General section), which lists all `BUILT_IN_TOOL_IDS` flat and shows each tool's attaching skill(s).
133
133
- `src/agent/promptFiles.ts` — File-backed store for each agent's `<Agent Name>/AGENT.md`. The code constant `DEFAULT_AGENT_PROMPT` remains the factory default the diff/reset UI compares against; the file is the editable copy. Values that must stay live are written into the body as placeholders (`{{memoryFolder}}`, `{{date}}`) and substituted by `substitutePromptPlaceholders` at assembly, so nothing stale is ever baked into stored text; assembly appends only what is irreducibly dynamic (the `# Skills` block, the no-write-tools guard). Each note carries a small plugin-managed frontmatter block (`author`, `version` — flat keys, so Obsidian's Properties UI renders them) whose `version` records the shipped baseline the body was written from, mirroring how skills version their SKILL.md; it is what makes "the default moved under YOUR edit" detectable, and it travels with the note through sync/copy (duplicating an agent copies the notes verbatim, provenance included). Everything model-facing uses the frontmatter-stripped **body** only — assembly, the diff modal, and the shipped-history fingerprints — so restamping never reads as a customization. Content is cached in memory as parsed body+version (populated at init + on vault change) so `assembleSystemPrompt` and the reactive stale-guidance getter read it without hitting disk. Editing happens in the vault note (pencil/"open note"); the `SystemPromptModal` diff modal stays for comparing against the default and resetting. Because the note lives in a folder of its own, rename/duplicate/delete are directory operations. (Skill/tool guidance is no longer stored here — it's the skill body, edited via the note / `manage_skills`.)
134
134
-`src/stores/` — Reactive state via Svelte 5 runes (`*.svelte.ts`). `dataStore` is canonical config + secrets indirection (its non-store residents live beside it: `agentDefaults.ts` for the default agent + load-time normalization, `dataMigrations.ts` for the schema version + migration table, `staleGuidance.ts` for the prompt-staleness detector); `chatStore` owns `ChatSession` and the `SessionRegistry`, while everything that *derives* the timeline from checkpoint history (checkpoint graph, `MessagePair`s, tool timelines, summarization markers, context blocks) is the pure, rune-free `chatTimeline.ts`; `pendingChangesStore` stages note mutations for review. `state.svelte.ts` is a leaf (plugin handle only) — nothing under `stores/` may be imported by `providers/*` or `utils/*`; see the import-cycle rule below.
135
135
-`src/components/` — Feature-vertical Svelte UI: `chat/`, `graph/`, `settings/`, `modal/`, plus shared `ui/` primitives. Markdown rendering goes through Obsidian's renderer (not a custom one). A modal whose body is a Svelte component extends `modal/SvelteModal.ts` (`mountComponent(component, props, layout?)`; it owns mount/unmount and the layout override) rather than re-implementing the lifecycle.
"Create new skills, revise the agent's own attached skills, or delete skills it created. Changes apply immediately. A skill's name and plugin link are locked once created.",
188
+
"Create new skills, revise the agent's own attached skills, or delete a skill when you ask it to. Changes apply immediately. A skill's name and plugin link are locked once created.",
189
189
config: {
190
190
// On by default: the routing doctrine in the memory section and the `# Skills`
191
191
// header both send task lessons into the skill that was used, and the post-turn
"Create new skills, revise your own attached skills, or delete skills you created. Changes apply immediately. A skill's name and plugin link are locked once created; only the body and description can change.",
197
+
"Create new skills, revise your own attached skills, or delete a skill when the user asks you to. Changes apply immediately. A skill's name and plugin link are locked once created; only the body and description can change.",
* Tool letting an agent create new skills, revise skills attached to it, or delete skills it
247
-
* created. All three operations apply immediately — there is no staging/review step, unlike
250
+
* Tool letting an agent create new skills, revise skills attached to it, or delete an attached
251
+
* skill the user asked it to delete. All three operations apply immediately — there is no staging/review step, unlike
248
252
* manage_notes. A created skill is given no explicit `agent.skills` entry, so it reads as
249
253
* attached the moment its file exists (agent.skills[id]?.enabled ?? true): creating IS attaching,
250
254
* with no separate manual "enable" step.
@@ -412,7 +416,7 @@ export function createManageSkillsTool(skillsService: SkillsService | undefined,
412
416
},
413
417
{
414
418
name: "manage_skills",
415
-
description: `Create new skills, revise your own attached skills, or delete skills you created. Changes apply immediately — there is no review step. To revise, load the skill with load_skill first, then patch the exact passage that needs changing (update replaces the whole body; use it only to restructure). A skill's name and plugin link are locked once created. Attached skills: ${attachedAtBuild.join(", ")}`,
419
+
description: `Create new skills, revise your own attached skills, or delete a skill when the user asks you to. Changes apply immediately — there is no review step. To revise, load the skill with load_skill first, then patch the exact passage that needs changing (update replaces the whole body; use it only to restructure). A skill's name and plugin link are locked once created. Attached skills: ${attachedAtBuild.join(", ")}`,
Copy file name to clipboardExpand all lines: src/skills/defaults/manage-skills/SKILL.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,10 @@
1
1
---
2
2
name: manage-skills
3
-
description: Create, revise, or delete skills with manage_skills — author new skills, fold verified knowledge into an existing skill's instructions, or remove a skill you created. Changes apply immediately. Load this before editing or creating a skill.
3
+
description: Create, revise, or delete skills with manage_skills — author new skills, fold verified knowledge into an existing skill's instructions, or remove a skill the user asked to delete. Changes apply immediately. Load this before editing or creating a skill.
4
4
allowed-tools: manage_skills
5
5
metadata:
6
6
author: "S2B"
7
-
version: "1.2"
7
+
version: "1.3"
8
8
category: "core"
9
9
---
10
10
@@ -48,5 +48,6 @@ an allowed subset are granted, others are silently dropped.
48
48
- Keep new skills narrow and instructions concrete — write down only what you'd actually want to
49
49
remember doing again.
50
50
51
-
**Delete** — remove a skill you created, immediately and without confirmation. Built-in core
52
-
skills cannot be deleted.
51
+
**Delete** — remove a skill only when the user asks for that skill to be deleted, whoever
52
+
wrote it. Never delete one on your own initiative, to tidy up or because it looks unused. It
53
+
applies immediately, with no confirmation step. Built-in core skills cannot be deleted.
0 commit comments