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 <noreply@anthropic.com>
This commit is contained in:
1 parent
8be453b361
commit
359ea0cba0
17 files changed
+85
-95
No files matched your search
@@ -9,7 +9,7 @@ Compatible with Claude Code, Codex, Gemini CLI, Cursor, Copilot, Windsurf, Cline
|
||||
|
||||
## Naming 🏷️
|
||||
|
||||
Every first-party skill is named `kvb-<category>-<name>` 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-<category>-<name>` 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 (`<repo>/.agents/skills` and `<repo>/.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.
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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/<name>/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
|
||||
@@ -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.
|
||||
+2
-7
@@ -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.
|
||||
@@ -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.
|
||||
---
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 |`.
|
||||
@@ -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(
|
||||
|
||||
+14
-14
@@ -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)
|
||||
|
||||
@@ -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]+)*$")
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user