From 359ea0cba0a17c5c135828fc281b6d6f3c56ee42 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Tue, 3 Nov 2026 13:08:31 +0100 Subject: [PATCH] feat(skills)!: rename the skills category to skill kvb-skills-dream, -tune, -auto, -essence and -transcend become kvb-skill-*, and tests/test_naming.py now requires the category skill. enable-plugins.js registers the reminder hooks under the new names and repoints hook commands of the previous kvb-skills-* paths as well as the older autotune/dream paths; test_dream covers both generations. References in kvb-check-confidence, kvb-org-perform, kvb-org-rasci, kvb-transcend, the tests and the README organigram and skill map follow. The header comments of both reminder hooks and enable-plugins.js are dropped. BREAKING CHANGE: /kvb-skills-dream, /kvb-skills-tune, /kvb-skills-auto, /kvb-skills-essence and /kvb-skills-transcend are now /kvb-skill-*. Co-Authored-By: Claude Opus 5.5 --- README.md | 36 +++++++++---------- scripts/enable-plugins.js | 12 +++---- skills/kvb-check-confidence/SKILL.md | 2 +- skills/kvb-org-perform/SKILL.md | 2 +- skills/kvb-org-rasci/SKILL.md | 2 +- .../SKILL.md | 6 ++-- .../SKILL.md | 12 +++---- .../hooks/reminder.sh | 9 ++--- .../SKILL.md | 4 +-- .../SKILL.md | 8 ++--- .../SKILL.md | 18 +++++----- .../hooks/reminder.sh | 7 ++-- skills/kvb-transcend/SKILL.md | 4 +-- tests/test_autotune.py | 18 +++++----- tests/test_dream.py | 28 +++++++-------- tests/test_naming.py | 2 +- tests/test_optimize.py | 10 +++--- 17 files changed, 85 insertions(+), 95 deletions(-) rename skills/{kvb-skills-auto => kvb-skill-auto}/SKILL.md (89%) rename skills/{kvb-skills-dream => kvb-skill-dream}/SKILL.md (95%) rename skills/{kvb-skills-dream => kvb-skill-dream}/hooks/reminder.sh (60%) rename skills/{kvb-skills-essence => kvb-skill-essence}/SKILL.md (97%) rename skills/{kvb-skills-transcend => kvb-skill-transcend}/SKILL.md (92%) rename skills/{kvb-skills-tune => kvb-skill-tune}/SKILL.md (92%) rename skills/{kvb-skills-tune => kvb-skill-tune}/hooks/reminder.sh (63%) diff --git a/README.md b/README.md index e35cba4..48f0b1a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Compatible with Claude Code, Codex, Gemini CLI, Cursor, Copilot, Windsurf, Cline ## Naming 🏷️ -Every first-party skill is named `kvb--` with one of these categories: `think`, `create`, `code`, `ci`, `git`, `check`, `org`, `skills`. Only `kvb-cleanup`, `kvb-help` and the collector `kvb-transcend` stand without a category. Names use `a-z`, `0-9` and single hyphens, at most 64 characters, and equal their directory name. `tests/test_naming.py` enforces all of it, including that the organigram below lists every skill under its category. +Every first-party skill is named `kvb--` with one of these categories: `think`, `create`, `code`, `ci`, `git`, `check`, `org`, `skill`. Only `kvb-cleanup`, `kvb-help` and the collector `kvb-transcend` stand without a category. Names use `a-z`, `0-9` and single hyphens, at most 64 characters, and equal their directory name. `tests/test_naming.py` enforces all of it, including that the organigram below lists every skill under its category. ## Organigram 🏛️ @@ -25,7 +25,7 @@ flowchart LR kvb --> git[git] kvb --> check[check] kvb --> org[org] - kvb --> skills[skills] + kvb --> skill[skill] kvb --> none[no category] think --> think_listen[kvb-think-listen] think --> think_explain[kvb-think-explain] @@ -64,11 +64,11 @@ flowchart LR org --> org_artefacts[kvb-org-artefacts] org --> org_wsjf[kvb-org-wsjf] org --> org_robot[kvb-org-robot] - skills --> skills_dream[kvb-skills-dream] - skills --> skills_tune[kvb-skills-tune] - skills --> skills_auto[kvb-skills-auto] - skills --> skills_essence[kvb-skills-essence] - skills --> skills_transcend[kvb-skills-transcend] + skill --> skill_dream[kvb-skill-dream] + skill --> skill_tune[kvb-skill-tune] + skill --> skill_auto[kvb-skill-auto] + skill --> skill_essence[kvb-skill-essence] + skill --> skill_transcend[kvb-skill-transcend] none --> cleanup[kvb-cleanup] none --> help[kvb-help] none --> transcend_all[kvb-transcend] @@ -139,12 +139,12 @@ flowchart LR wsjf[kvb-org-wsjf] robot[kvb-org-robot] end - subgraph cat_skills [skills] - dream[kvb-skills-dream] - autotune[kvb-skills-tune] - autoskill[kvb-skills-auto] - essence[kvb-skills-essence] - skills_transcend[kvb-skills-transcend] + subgraph cat_skill [skill] + dream[kvb-skill-dream] + autotune[kvb-skill-tune] + autoskill[kvb-skill-auto] + essence[kvb-skill-essence] + skill_transcend[kvb-skill-transcend] end subgraph cat_none [no category] cleanup[kvb-cleanup] @@ -225,12 +225,12 @@ flowchart LR autoskill --> autotune autotune --> essence dream --> transcend - transcend --> skills_transcend + transcend --> skill_transcend transcend --> code_transcend - skills_transcend --> active_listening - skills_transcend --> autotune + skill_transcend --> active_listening + skill_transcend --> autotune code_transcend --> active_listening - autotune -. own scripts .-> skills_transcend + autotune -. own scripts .-> skill_transcend tune -. measurements .-> code_transcend test --> triage @@ -259,7 +259,7 @@ Copy the skills into a specific project (`/.agents/skills` and `/.cl make project TARGET=/path/to/repo ``` -Both commands also patch the target's `.claude/settings.local.json` — the machine-local, untracked file, so a project's reviewed `.claude/settings.json` is never rewritten by an install: the caveman and ponytail plugins are enabled so their modes auto-activate on session start, and two reminder hooks are registered — `kvb-skills-tune` points you at `/kvb-skills-tune` at most once an hour, `kvb-skills-dream` points you at `/kvb-skills-dream` at most once every twelve hours per repository (stamped in that repository's git dir). A PreToolUse gate from the `kvb-org-organize` skill blocks edits to files in a git worktree until the session holds a claim (`skills/kvb-org-organize/scripts/council.py`), and its resource watch (`skills/kvb-org-organize/scripts/watch.py`) measures disk, Docker and caches, cleans up low-risk data and blocks new heavy jobs before the disk runs out; it stays inactive until `~/.config/agents-council/config.json` exists. Two hooks of the `kvb-org-perform` skill (`skills/kvb-org-perform/scripts/log.py`) log every Agent spawn with its task class, model and effort, and store the quality feedback a sandboxed session prints, in `~/.local/state/agents-council/subagent-model.jsonl`. Existing settings are preserved. +Both commands also patch the target's `.claude/settings.local.json` — the machine-local, untracked file, so a project's reviewed `.claude/settings.json` is never rewritten by an install: the caveman and ponytail plugins are enabled so their modes auto-activate on session start, and two reminder hooks are registered — `kvb-skill-tune` points you at `/kvb-skill-tune` at most once an hour, `kvb-skill-dream` points you at `/kvb-skill-dream` at most once every twelve hours per repository (stamped in that repository's git dir). A PreToolUse gate from the `kvb-org-organize` skill blocks edits to files in a git worktree until the session holds a claim (`skills/kvb-org-organize/scripts/council.py`), and its resource watch (`skills/kvb-org-organize/scripts/watch.py`) measures disk, Docker and caches, cleans up low-risk data and blocks new heavy jobs before the disk runs out; it stays inactive until `~/.config/agents-council/config.json` exists. Two hooks of the `kvb-org-perform` skill (`skills/kvb-org-perform/scripts/log.py`) log every Agent spawn with its task class, model and effort, and store the quality feedback a sandboxed session prints, in `~/.local/state/agents-council/subagent-model.jsonl`. Existing settings are preserved. Restart your agent afterwards so it loads the new skills. diff --git a/scripts/enable-plugins.js b/scripts/enable-plugins.js index 1a2d8b4..021f62a 100644 --- a/scripts/enable-plugins.js +++ b/scripts/enable-plugins.js @@ -1,8 +1,4 @@ #!/usr/bin/env node -// Enable the caveman and ponytail plugins in a Claude Code settings.json so -// their SessionStart hooks auto-activate both modes, register the kvb-skills-tune -// and kvb-skills-dream reminder hooks, the kvb-org-organize claim gate, the resource watch and the kvb-org-perform log. Merges non-destructively: existing marketplaces, -// plugins and hooks are preserved, hooks of renamed skills are repointed, unparseable files are left untouched. "use strict"; const fs = require("fs"); @@ -19,10 +15,12 @@ const MARKETPLACES = { ponytail: { source: { source: "github", repo: "DietrichGebert/ponytail" } }, }; const PLUGINS = { "caveman@caveman": true, "ponytail@ponytail": true }; -const REMINDERS = ["kvb-skills-tune", "kvb-skills-dream"]; +const REMINDERS = ["kvb-skill-tune", "kvb-skill-dream"]; const RENAMED = { - "autotune/hooks/reminder.sh": "kvb-skills-tune/hooks/reminder.sh", - "dream/hooks/reminder.sh": "kvb-skills-dream/hooks/reminder.sh", + "autotune/hooks/reminder.sh": "kvb-skill-tune/hooks/reminder.sh", + "dream/hooks/reminder.sh": "kvb-skill-dream/hooks/reminder.sh", + "kvb-skills-tune/hooks/reminder.sh": "kvb-skill-tune/hooks/reminder.sh", + "kvb-skills-dream/hooks/reminder.sh": "kvb-skill-dream/hooks/reminder.sh", "democracy/scripts/council.py": "kvb-org-organize/scripts/council.py", "democracy/scripts/watch.py": "kvb-org-organize/scripts/watch.py", "subagent-model/scripts/log.py": "kvb-org-perform/scripts/log.py", diff --git a/skills/kvb-check-confidence/SKILL.md b/skills/kvb-check-confidence/SKILL.md index b495d1f..0ca4609 100644 --- a/skills/kvb-check-confidence/SKILL.md +++ b/skills/kvb-check-confidence/SKILL.md @@ -36,5 +36,5 @@ A threshold the operator named ("95% confidence, break risk ≤5%") is a gate on the work, handled as the `kvb-check-break-risk` skill's last section says, for both numbers. -Objective: the `kvb-skills-tune` skill's **Objective** section. Two figures with their residuals replace a +Objective: the `kvb-skill-tune` skill's **Objective** section. Two figures with their residuals replace a hedging paragraph and save the operator a verification round trip. diff --git a/skills/kvb-org-perform/SKILL.md b/skills/kvb-org-perform/SKILL.md index b18c3ad..c0eff50 100644 --- a/skills/kvb-org-perform/SKILL.md +++ b/skills/kvb-org-perform/SKILL.md @@ -68,7 +68,7 @@ Inside a sandbox that cannot write it, the script prints the line as runs and the share with the same result: completed, not redone, no failing test, no follow-up. A row is added, or a cheaper setting extended to a class, only when the report shows at least 90 % over at least 20 rated runs, and only -after the operator confirms it (for example through `/kvb-skills-tune`). A row whose +after the operator confirms it (for example through `/kvb-skill-tune`). A row whose rate falls below 90 % over 20 rated runs goes back to the default. `sonnet` enters the table only this way, and a trial run on a setting the table does not hold needs the operator's order. diff --git a/skills/kvb-org-rasci/SKILL.md b/skills/kvb-org-rasci/SKILL.md index 3e38c42..2afe8fa 100644 --- a/skills/kvb-org-rasci/SKILL.md +++ b/skills/kvb-org-rasci/SKILL.md @@ -53,7 +53,7 @@ published). `done` is refused while one is open; a task ended short of them is executing the task right now. - Artifacts share this table and follow the `kvb-org-artefacts` skill: record each one when it appears, drop it once deleted. Add every script or - tool the task ran (`--tool`): `tools` ranks them for `kvb-skills-dream`. + tool the task ran (`--tool`): `tools` ranks them for `kvb-skill-dream`. - Priority is the rank of the `kvb-org-wsjf` skill: an operator's pin (`--prio`) first, then WSJF from the estimates the chair collects; `show` prints the rank as Prio and the score as WSJF. diff --git a/skills/kvb-skills-auto/SKILL.md b/skills/kvb-skill-auto/SKILL.md similarity index 89% rename from skills/kvb-skills-auto/SKILL.md rename to skills/kvb-skill-auto/SKILL.md index 895ee43..4444186 100644 --- a/skills/kvb-skills-auto/SKILL.md +++ b/skills/kvb-skill-auto/SKILL.md @@ -1,12 +1,12 @@ --- -name: kvb-skills-auto +name: kvb-skill-auto description: > Turn operator repetition into a skill. Trigger when the operator repeats an instruction, correction or prompt pattern a third time in a conversation, or says they keep repeating themselves, and the pattern is reusable. --- -Its objective is the `kvb-skills-tune` skill's **Objective** section: a skill is worth +Its objective is the `kvb-skill-tune` skill's **Objective** section: a skill is worth creating only when it cuts tokens or time and raises quality; judge every candidate against its three axes and rules. @@ -19,7 +19,7 @@ vary), do the following: a skill name suggestion, the trigger phrasing, and what the skill would do. Ask whether to create it. 3. On approval, write the skill: persist it exactly as the - `kvb-skills-tune` skill's **Persistence** section specifies — locate the + `kvb-skill-tune` skill's **Persistence** section specifies — locate the operator's skills repository, write `skills//SKILL.md` there (or in the current project for project-specific behavior), then mirror the skill directory into `~/.claude/skills/` and `~/.agents/skills/`, plus the diff --git a/skills/kvb-skills-dream/SKILL.md b/skills/kvb-skill-dream/SKILL.md similarity index 95% rename from skills/kvb-skills-dream/SKILL.md rename to skills/kvb-skill-dream/SKILL.md index d2de619..4eed4ec 100644 --- a/skills/kvb-skills-dream/SKILL.md +++ b/skills/kvb-skill-dream/SKILL.md @@ -1,9 +1,9 @@ --- -name: kvb-skills-dream +name: kvb-skill-dream description: > Consolidate the last 24 hours of work in this repository (what held, what broke) into memory and improvement proposals. - Trigger on /kvb-skills-dream or a request to reflect on or learn from recent + Trigger on /kvb-skill-dream or a request to reflect on or learn from recent work. --- @@ -30,7 +30,7 @@ confidence the next run can now hold on each closed class, calibrated as the Everything is read from the repository the skill runs in (`git rev-parse --show-toplevel`); never mix in another project's history or memory. The default -window is the last 24 hours — the operator may widen it (`/kvb-skills-dream 7d`). State the +window is the last 24 hours — the operator may widen it (`/kvb-skill-dream 7d`). State the repository and the window in one line before you start. Run only when the operator asks. The 12-hour reminder hook @@ -109,10 +109,10 @@ as radio buttons: the improvement, the evidence behind it, and the options `Apply now`, `Record as a task`, `Skip`. Ranked by evidence, one question per improvement. No repository file changes before an answer comes back. -## Step 7: kvb-skills-tune, kvb-skills-auto, kvb-transcend +## Step 7: kvb-skill-tune, kvb-skill-auto, kvb-transcend -With the dialectic done and memory written, run `kvb-skills-tune` — hand it this run's -findings as its evidence so it does not re-collect them — then `kvb-skills-auto` +With the dialectic done and memory written, run `kvb-skill-tune` — hand it this run's +findings as its evidence so it does not re-collect them — then `kvb-skill-auto` for the operator corrections the window revealed, and `kvb-transcend` for the scripts and tests the window's sessions wrote outside a repository. All keep their own confirmation steps; the dream never writes a skill on their behalf. diff --git a/skills/kvb-skills-dream/hooks/reminder.sh b/skills/kvb-skill-dream/hooks/reminder.sh similarity index 60% rename from skills/kvb-skills-dream/hooks/reminder.sh rename to skills/kvb-skill-dream/hooks/reminder.sh index 5ba8de0..8952ffd 100755 --- a/skills/kvb-skills-dream/hooks/reminder.sh +++ b/skills/kvb-skill-dream/hooks/reminder.sh @@ -1,9 +1,4 @@ #!/usr/bin/env bash -# UserPromptSubmit hook: emit the kvb-skills-dream hint at most once per interval and per -# repository. The stamp lives in the repository's git dir, so every repository -# keeps its own cadence; outside a git repository the hook stays silent. -# Stdout lands in the agent's context, which is why the payload tells the agent -# to show the hint and keep going instead of running kvb-skills-dream by itself. set -euo pipefail interval="${DREAM_INTERVAL_SECONDS:-43200}" @@ -31,10 +26,10 @@ printf '%s\n' "${now}" >"${stamp}" cat <<'HINT' DREAM HINT: over twelve hours since the last hint for this repository. Show the operator this notice verbatim as a short block, then continue with their -request. Do NOT run kvb-skills-dream, do not start replaying the history, do +request. Do NOT run kvb-skill-dream, do not start replaying the history, do not ask questions about it. - 💤 /kvb-skills-dream - consolidate the last 24h in this repository: what + 💤 /kvb-skill-dream - consolidate the last 24h in this repository: what held, what broke, which hypotheses follow, into memory and improvement proposals. Runs only when you trigger it. diff --git a/skills/kvb-skills-essence/SKILL.md b/skills/kvb-skill-essence/SKILL.md similarity index 97% rename from skills/kvb-skills-essence/SKILL.md rename to skills/kvb-skill-essence/SKILL.md index a05379b..856c385 100644 --- a/skills/kvb-skills-essence/SKILL.md +++ b/skills/kvb-skill-essence/SKILL.md @@ -1,8 +1,8 @@ --- -name: kvb-skills-essence +name: kvb-skill-essence description: > Compact skills and memory to their essence after a health pass that finds - dead weight. Trigger on /kvb-skills-essence or when skills or MEMORY.md grow too long, + dead weight. Trigger on /kvb-skill-essence or when skills or MEMORY.md grow too long, duplicate, or eat too much context. --- diff --git a/skills/kvb-skills-transcend/SKILL.md b/skills/kvb-skill-transcend/SKILL.md similarity index 92% rename from skills/kvb-skills-transcend/SKILL.md rename to skills/kvb-skill-transcend/SKILL.md index b23ab12..ba81c4e 100644 --- a/skills/kvb-skills-transcend/SKILL.md +++ b/skills/kvb-skill-transcend/SKILL.md @@ -1,8 +1,8 @@ --- -name: kvb-skills-transcend +name: kvb-skill-transcend description: > Carry the session's skill use and own scripts into the skills repo. - Trigger on /kvb-skills-transcend. + Trigger on /kvb-skill-transcend. --- What an agent improvised in one session dies with it: the helper script in its @@ -31,7 +31,7 @@ One line each: `candidate -> source -> evidence`. Per candidate one target: a script under an existing skill's `scripts/`, a new skill, a sharper step in an existing skill, a memory entry instead, or -drop. Recurring moves without a script go to the `kvb-skills-tune` skill as +drop. Recurring moves without a script go to the `kvb-skill-tune` skill as evidence. A script is portable only once its host paths, names and values became explicit parameters (the `kvb-code-no-defaults` skill); one that needs a secret, a credential or a single host is dropped or stays a memory entry. @@ -46,7 +46,7 @@ diff. ## Step 4: write -- Write where the `kvb-skills-tune` skill's **Persistence** section says: +- Write where the `kvb-skill-tune` skill's **Persistence** section says: the skills repository as source of truth, then the live mirrors. - Read every script whole before carrying it; strip comments the way the `kvb-code-no-comments` skill does. diff --git a/skills/kvb-skills-tune/SKILL.md b/skills/kvb-skill-tune/SKILL.md similarity index 92% rename from skills/kvb-skills-tune/SKILL.md rename to skills/kvb-skill-tune/SKILL.md index 369b950..9079084 100644 --- a/skills/kvb-skills-tune/SKILL.md +++ b/skills/kvb-skill-tune/SKILL.md @@ -1,9 +1,9 @@ --- -name: kvb-skills-tune +name: kvb-skill-tune description: > Generate new skills or optimize existing ones (fewer tokens and errors, persistent learnings), each proposal confirmed. Trigger ONLY on an explicit - request: /kvb-skills-tune, "autotune", "tune the skills". + request: /kvb-skill-tune, "autotune", "tune the skills". --- Autotune turns observed friction into durable skills. It runs on demand only, @@ -12,8 +12,8 @@ skill it writes or rewrites lands in the operator's skills repository. ## Objective -The shared objective of the self-improving skills (kvb-skills-tune, -kvb-skills-auto, kvb-check-confidence): every skill, rule, or report the agent produces about its own +The shared objective of the self-improving skills (kvb-skill-tune, +kvb-skill-auto, kvb-check-confidence): every skill, rule, or report the agent produces about its own working is judged on three axes at once. A proposal that cannot name the axis it moves is not an optimization, it is a preference. @@ -42,7 +42,7 @@ it moves is not an optimization, it is a preference. ## Trigger discipline -- Run **only** when the operator asks: `/kvb-skills-tune`, "autotune", "tune the +- Run **only** when the operator asks: `/kvb-skill-tune`, "autotune", "tune the skills", or an equivalent instruction. - The 60-minute reminder hook is a hint for the operator, not a trigger. When it fires, print the hint and continue the operator's actual request. @@ -63,7 +63,7 @@ where readable, from the project's memory and agent instruction files: - **Lost learnings**: facts re-derived this session that a memory file or a skill should already have carried. - **Own scripts**: helpers the agent wrote outside any repository belong to - the `kvb-skills-transcend` skill, which carries them over; this skill + the `kvb-skill-transcend` skill, which carries them over; this skill takes the frictions they reveal. List each finding as one line: `symptom -> cost -> candidate fix`. Skip @@ -77,7 +77,7 @@ option, and never write a file before the answers are in. Ask in this order, at most four questions per call: -1. **Scope** - "What should kvb-skills-tune do this run?" Options: `Create a new +1. **Scope** - "What should kvb-skill-tune do this run?" Options: `Create a new skill`, `Optimize an existing skill`, `Both`, plus the ranked findings if more than one candidate exists. 2. **Target** - which finding becomes a skill, or which existing skill gets @@ -132,7 +132,7 @@ reverse — remove the mirrors too, or the old name keeps firing. - Optimizing an existing skill means the file gets shorter or sharper, not longer. Delete rules the agent already follows, merge duplicated ones, and cut every sentence that does not change an action. Route that compaction - through the `kvb-skills-essence` skill instead of trimming by hand: it runs a health + through the `kvb-skill-essence` skill instead of trimming by hand: it runs a health pass for dead pointers and rules duplicated across skills before cutting anything, ranks by what loads in every session, and shows the diff before it writes. It asks for its own scope — answer with the skill being optimized. @@ -142,7 +142,7 @@ reverse — remove the mirrors too, or the old name keeps firing. ## Rules - One skill per run unless the operator picked `Both`; a broad rewrite of the - whole collection is not what kvb-skills-tune is for. + whole collection is not what kvb-skill-tune is for. - Never write a skill for one-off work, for secrets, or for behaviour an existing skill already covers - propose extending that skill instead. - The **Objective** section decides what counts as an improvement: at least diff --git a/skills/kvb-skills-tune/hooks/reminder.sh b/skills/kvb-skill-tune/hooks/reminder.sh similarity index 63% rename from skills/kvb-skills-tune/hooks/reminder.sh rename to skills/kvb-skill-tune/hooks/reminder.sh index dfbfae9..817a2a8 100755 --- a/skills/kvb-skills-tune/hooks/reminder.sh +++ b/skills/kvb-skill-tune/hooks/reminder.sh @@ -1,7 +1,4 @@ #!/usr/bin/env bash -# UserPromptSubmit hook: emit the kvb-skills-tune hint at most once per interval. -# Stdout lands in the agent's context, which is why the payload tells the agent -# to show the hint and keep going instead of running kvb-skills-tune by itself. set -euo pipefail interval="${AUTOTUNE_INTERVAL_SECONDS:-3600}" @@ -24,9 +21,9 @@ printf '%s\n' "${now}" >"${stamp}" cat <<'HINT' AUTOTUNE HINT: over an hour since the last hint. Show the operator this notice verbatim as a short block, then continue with their request. Do NOT run -kvb-skills-tune, do not propose skills, do not ask questions about it. +kvb-skill-tune, do not propose skills, do not ask questions about it. - 💡 /kvb-skills-tune - generate a new skill or optimize an existing one + 💡 /kvb-skill-tune - generate a new skill or optimize an existing one (fewer tokens, fewer errors, more focus, learnings that persist). Runs only when you trigger it. HINT diff --git a/skills/kvb-transcend/SKILL.md b/skills/kvb-transcend/SKILL.md index 913e95d..f3a0515 100644 --- a/skills/kvb-transcend/SKILL.md +++ b/skills/kvb-transcend/SKILL.md @@ -4,7 +4,7 @@ description: > Run both transcend skills in one pass. Trigger on /kvb-transcend. --- -Collector for the `kvb-skills-transcend` and `kvb-code-transcend` skills, so +Collector for the `kvb-skill-transcend` and `kvb-code-transcend` skills, so one harvest needs one round of questions. Its script finds the candidates and remembers every decision, so a rescan offers only what is new or changed: @@ -29,7 +29,7 @@ every time. 3. One `kvb-think-listen` round and one confirmation for all candidates, grouped by target: the skills repository or the current repository. In the skills repository itself, scripts and skills go to - `kvb-skills-transcend`, tests to `kvb-code-transcend`. + `kvb-skill-transcend`, tests to `kvb-code-transcend`. 4. Hand each confirmed candidate to its skill's write step, then `mark` every offered candidate with its verdict. 5. One table: `| Candidate | Source | Target | Verdict |`. diff --git a/tests/test_autotune.py b/tests/test_autotune.py index 4b70e65..c4acc6e 100644 --- a/tests/test_autotune.py +++ b/tests/test_autotune.py @@ -1,4 +1,4 @@ -"""Validate the kvb-skills-tune reminder hook and its settings registration.""" +"""Validate the kvb-skill-tune reminder hook and its settings registration.""" from __future__ import annotations @@ -10,8 +10,8 @@ import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] -SKILL = REPO_ROOT / "skills" / "kvb-skills-tune" / "SKILL.md" -HOOK = REPO_ROOT / "skills" / "kvb-skills-tune" / "hooks" / "reminder.sh" +SKILL = REPO_ROOT / "skills" / "kvb-skill-tune" / "SKILL.md" +HOOK = REPO_ROOT / "skills" / "kvb-skill-tune" / "hooks" / "reminder.sh" PATCHER = REPO_ROOT / "scripts" / "enable-plugins.js" @@ -33,7 +33,7 @@ def _run_hook(stamp: Path, interval: str = "3600") -> subprocess.CompletedProces class TestAutotuneSkill(unittest.TestCase): def test_skill_is_trigger_only(self): text = SKILL.read_text(encoding="utf-8") - self.assertIn("name: kvb-skills-tune", text) + self.assertIn("name: kvb-skill-tune", text) self.assertIn("multiSelect: false", text) @@ -51,7 +51,7 @@ class TestSkillPersistence(unittest.TestCase): self.assertIn(target, text) def test_autoskill_routes_to_the_same_persistence(self): - text = (REPO_ROOT / "skills" / "kvb-skills-auto" / "SKILL.md").read_text( + text = (REPO_ROOT / "skills" / "kvb-skill-auto" / "SKILL.md").read_text( encoding="utf-8" ) for target in ("Persistence", "~/.claude/skills/", "~/.agents/skills/"): @@ -66,7 +66,7 @@ class TestAutotuneHook(unittest.TestCase): def test_first_run_hints_and_stamps(self): result = _run_hook(self.stamp) - self.assertIn("/kvb-skills-tune", result.stdout) + self.assertIn("/kvb-skill-tune", result.stdout) self.assertTrue(self.stamp.is_file()) def test_second_run_is_silent_within_interval(self): @@ -75,12 +75,12 @@ class TestAutotuneHook(unittest.TestCase): def test_hint_returns_after_the_interval(self): _run_hook(self.stamp) - self.assertIn("/kvb-skills-tune", _run_hook(self.stamp, interval="0").stdout) + self.assertIn("/kvb-skill-tune", _run_hook(self.stamp, interval="0").stdout) def test_corrupt_stamp_does_not_crash(self): self.stamp.parent.mkdir(parents=True, exist_ok=True) self.stamp.write_text("not-a-timestamp\n", encoding="utf-8") - self.assertIn("/kvb-skills-tune", _run_hook(self.stamp).stdout) + self.assertIn("/kvb-skill-tune", _run_hook(self.stamp).stdout) @unittest.skipUnless(shutil.which("node"), "node not installed") @@ -100,7 +100,7 @@ class TestSettingsRegistration(unittest.TestCase): self._patch() data = self._patch() entries = json.dumps(data["hooks"]["UserPromptSubmit"]) - self.assertEqual(entries.count("kvb-skills-tune/hooks/reminder.sh"), 1) + self.assertEqual(entries.count("kvb-skill-tune/hooks/reminder.sh"), 1) def test_existing_hooks_preserved(self): self.settings.write_text( diff --git a/tests/test_dream.py b/tests/test_dream.py index 7504d91..0475762 100644 --- a/tests/test_dream.py +++ b/tests/test_dream.py @@ -10,8 +10,8 @@ import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] -SKILL = REPO_ROOT / "skills" / "kvb-skills-dream" / "SKILL.md" -HOOK = REPO_ROOT / "skills" / "kvb-skills-dream" / "hooks" / "reminder.sh" +SKILL = REPO_ROOT / "skills" / "kvb-skill-dream" / "SKILL.md" +HOOK = REPO_ROOT / "skills" / "kvb-skill-dream" / "hooks" / "reminder.sh" PATCHER = REPO_ROOT / "scripts" / "enable-plugins.js" @@ -38,7 +38,7 @@ def _run_hook( class TestDreamSkill(unittest.TestCase): def test_skill_is_trigger_only(self): text = SKILL.read_text(encoding="utf-8") - self.assertIn("name: kvb-skills-dream", text) + self.assertIn("name: kvb-skill-dream", text) self.assertIn("multiSelect: false", text) @@ -51,7 +51,7 @@ class TestDreamHook(unittest.TestCase): def test_first_run_hints_and_stamps(self): result = _run_hook(self.cwd, self.stamp) - self.assertIn("/kvb-skills-dream", result.stdout) + self.assertIn("/kvb-skill-dream", result.stdout) self.assertTrue(self.stamp.is_file()) def test_second_run_is_silent_within_interval(self): @@ -60,12 +60,12 @@ class TestDreamHook(unittest.TestCase): def test_hint_returns_after_the_interval(self): _run_hook(self.cwd, self.stamp) - self.assertIn("/kvb-skills-dream", _run_hook(self.cwd, self.stamp, interval="0").stdout) + self.assertIn("/kvb-skill-dream", _run_hook(self.cwd, self.stamp, interval="0").stdout) def test_corrupt_stamp_does_not_crash(self): self.stamp.parent.mkdir(parents=True, exist_ok=True) self.stamp.write_text("not-a-timestamp\n", encoding="utf-8") - self.assertIn("/kvb-skills-dream", _run_hook(self.cwd, self.stamp).stdout) + self.assertIn("/kvb-skill-dream", _run_hook(self.cwd, self.stamp).stdout) def test_outside_a_repository_it_stays_silent(self): self.assertEqual(_run_hook(self.cwd).stdout, "") @@ -78,7 +78,7 @@ class TestDreamHook(unittest.TestCase): subprocess.run( ["git", "init", "-q", str(repo)], check=True, capture_output=True ) - self.assertIn("/kvb-skills-dream", _run_hook(repo).stdout) + self.assertIn("/kvb-skill-dream", _run_hook(repo).stdout) self.assertTrue((repo / ".git" / ".dream-stamp").is_file()) self.assertEqual(_run_hook(repo).stdout, "") @@ -103,7 +103,7 @@ class TestDreamHook(unittest.TestCase): subprocess.run( ["git", *args], check=True, capture_output=True, env=env, cwd=str(repo) ) - self.assertIn("/kvb-skills-dream", _run_hook(repo).stdout) + self.assertIn("/kvb-skill-dream", _run_hook(repo).stdout) self.assertEqual(_run_hook(tree).stdout, "") @@ -124,8 +124,8 @@ class TestSettingsRegistration(unittest.TestCase): self._patch() data = self._patch() entries = json.dumps(data["hooks"]["UserPromptSubmit"]) - self.assertEqual(entries.count("kvb-skills-dream/hooks/reminder.sh"), 1) - self.assertEqual(entries.count("kvb-skills-tune/hooks/reminder.sh"), 1) + self.assertEqual(entries.count("kvb-skill-dream/hooks/reminder.sh"), 1) + self.assertEqual(entries.count("kvb-skill-tune/hooks/reminder.sh"), 1) gate = json.dumps(data["hooks"]["PreToolUse"]) self.assertEqual(gate.count("kvb-org-organize/scripts/council.py"), 1) self.assertEqual(gate.count("kvb-org-organize/scripts/watch.py"), 1) @@ -147,7 +147,7 @@ class TestSettingsRegistration(unittest.TestCase): "hooks": { "UserPromptSubmit": [ hook(f'bash "{base}/autotune/hooks/reminder.sh"'), - hook(f'bash "{base}/dream/hooks/reminder.sh"'), + hook(f'bash "{base}/kvb-skills-dream/hooks/reminder.sh"'), hook(f'python3 "{base}/democracy/scripts/watch.py" watch'), hook("echo keep"), ], @@ -167,12 +167,12 @@ class TestSettingsRegistration(unittest.TestCase): ) data = self._patch() text = json.dumps(data["hooks"]) - for old in ("/autotune/", "/dream/", "/democracy/", "/subagent-model/"): + for old in ("/autotune/", "/kvb-skills-dream/", "/democracy/", "/subagent-model/"): self.assertNotIn(f"skills{old}", text) self.assertIn("echo keep", text) entries = json.dumps(data["hooks"]["UserPromptSubmit"]) - self.assertEqual(entries.count("kvb-skills-dream/hooks/reminder.sh"), 1) - self.assertEqual(entries.count("kvb-skills-tune/hooks/reminder.sh"), 1) + self.assertEqual(entries.count("kvb-skill-dream/hooks/reminder.sh"), 1) + self.assertEqual(entries.count("kvb-skill-tune/hooks/reminder.sh"), 1) self.assertEqual(entries.count("kvb-org-organize/scripts/watch.py"), 1) gate = json.dumps(data["hooks"]["PreToolUse"]) self.assertEqual(gate.count("kvb-org-organize/scripts/council.py"), 1) diff --git a/tests/test_naming.py b/tests/test_naming.py index 995ac45..1884fca 100644 --- a/tests/test_naming.py +++ b/tests/test_naming.py @@ -9,7 +9,7 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] SKILLS = REPO_ROOT / "skills" README = REPO_ROOT / "README.md" -CATEGORIES = ("think", "create", "code", "ci", "git", "check", "org", "skills") +CATEGORIES = ("think", "create", "code", "ci", "git", "check", "org", "skill") UNCATEGORIZED = frozenset({"kvb-cleanup", "kvb-help", "kvb-transcend"}) SPEC = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$") SCHEMA = re.compile(rf"^kvb-(?:{'|'.join(CATEGORIES)})-[a-z0-9]+(?:-[a-z0-9]+)*$") diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 64f4030..0d89c44 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -1,4 +1,4 @@ -"""The self-improving skills must share the objective held by kvb-skills-tune.""" +"""The self-improving skills must share the objective held by kvb-skill-tune.""" from __future__ import annotations @@ -7,12 +7,12 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] SKILLS = REPO_ROOT / "skills" -ROUTERS = ("kvb-skills-auto", "kvb-check-confidence") +ROUTERS = ("kvb-skill-auto", "kvb-check-confidence") class TestOptimizeObjective(unittest.TestCase): def test_autotune_names_the_three_axes(self): - text = (SKILLS / "kvb-skills-tune" / "SKILL.md").read_text(encoding="utf-8") + text = (SKILLS / "kvb-skill-tune" / "SKILL.md").read_text(encoding="utf-8") self.assertIn("## Objective", text) for axis in ("**Tokens**", "**Time**", "**Quality**"): self.assertIn(axis, text) @@ -21,9 +21,9 @@ class TestOptimizeObjective(unittest.TestCase): for skill in ROUTERS: text = (SKILLS / skill / "SKILL.md").read_text(encoding="utf-8") self.assertIn( - "`kvb-skills-tune` skill's **Objective**", + "`kvb-skill-tune` skill's **Objective**", text, - f"{skill} does not route to the kvb-skills-tune objective", + f"{skill} does not route to the kvb-skill-tune objective", )