From 780289a40f3c6df74ba652d071bed295081f692e Mon Sep 17 00:00:00 2001 From: Ryan Leckenby Date: Sun, 26 Jul 2026 23:00:53 -0400 Subject: [PATCH] Document the skill system: taxonomy, meta-skill, case study, index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the skill/knowledge system legible to a public visitor and self-propagating: - knowledge/notes/skill-vs-note-vs-code.md: the decision rule for what becomes a skill vs. a knowledge note vs. tested code, with boundary cases and rejected alternatives. - .claude/skills/write-skill/SKILL.md: a meta-skill that scaffolds new skills in the house style (frontmatter + Steps + Do not), then registers and logs them. - knowledge/notes/case-study-github-project-tracking.md: a worked, real example of the github-* skills end to end — the run they were generalized from. - README.md: a Skills index table + links to the taxonomy note and case study. - CLAUDE.md / LOG.md: register write-skill and log the change. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/write-skill/SKILL.md | 55 +++++++++++++++++ CLAUDE.md | 6 +- LOG.md | 1 + README.md | 30 ++++++++- .../case-study-github-project-tracking.md | 52 ++++++++++++++++ knowledge/notes/skill-vs-note-vs-code.md | 61 +++++++++++++++++++ 6 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 .claude/skills/write-skill/SKILL.md create mode 100644 knowledge/notes/case-study-github-project-tracking.md create mode 100644 knowledge/notes/skill-vs-note-vs-code.md diff --git a/.claude/skills/write-skill/SKILL.md b/.claude/skills/write-skill/SKILL.md new file mode 100644 index 0000000..ad81514 --- /dev/null +++ b/.claude/skills/write-skill/SKILL.md @@ -0,0 +1,55 @@ +--- +name: write-skill +description: Scaffold a new Claude Code skill in this repo's house style — a `.claude/skills//SKILL.md` with correct frontmatter (name + a trigger-rich description), an intro, numbered `## Steps`, and a `## Do not` section — then register it in CLAUDE.md and log it. Use when the user wants to capture a repeatable procedure as a reusable skill ("make a skill for X", "turn this into a skill", "we keep doing X, let's skill-ify it"). First confirm it's actually a skill and not a note or code (see the skill-vs-note-vs-code knowledge note). +--- + +# write-skill + +Skills in this repo share one shape, and a skill that doesn't match it either won't trigger when +it should (weak `description`) or won't be followable when it does (vague steps). This skill is the +recipe for writing a new one correctly, and it keeps the catalog self-propagating — the repo can +grow its own skills instead of being hand-copied. + +## Steps + +1. **Confirm it's really a skill.** A skill is a *repeatable procedure* with a trigger. If it's a + fact/decision it's a `note`; if it's deterministic testable logic it's `code`. When unsure, read + `knowledge/notes/skill-vs-note-vs-code.md` and decide before creating anything. +2. **Get the essentials** (ask if not supplied): + - **Name** — short, kebab-case (`review-signals`, `github-cli-setup`). Becomes the folder name. + - **When to use it** — the concrete triggers, ideally including the phrases a user would say. + - **The procedure** — the ordered steps, and any hard "never do this" rules. +3. **Check for duplication/overlap.** Look at the existing `.claude/skills/*/SKILL.md`. If a skill + already covers this, extend it rather than adding a near-duplicate (e.g. don't add a PR-flow + skill when `ship-loop-change` already owns verify→commit→PR). +4. **Write `.claude/skills//SKILL.md`** in the house style: + - **Frontmatter** — `name:` (matches the folder) and `description:`. The `description` is what + triggers the skill, so make it do double duty: *what* it does **and** *when* to use it, + including trigger phrases. Study the descriptions on `new-loop` and `review-signals` for the + length and specificity to match. + - **`# `** heading, then a short intro: the problem this solves and when to reach for it. + - **`## Steps`** — numbered, imperative, concrete. Name the actual commands/paths/fields, not + "do the thing." Where a step is deterministic, point at code to call rather than prose to + re-derive. + - **`## Do not`** — the failure modes and hard boundaries. This is where hard-won lessons live; + don't skip it. +5. **Keep it generic** unless it's deliberately project-specific — a skill should read the same + regardless of which project pulled in this template. +6. **Register it in `CLAUDE.md`** — add a line to the `.claude/skills/` entry in the repo map so a + session knows the skill exists. +7. **Log it** — append one line to the root `LOG.md` (newest at top): + `YYYY-MM-DD HH:MM | scaffold | added skill — | [[.claude/skills//SKILL.md]]`. +8. **Ship it** via `ship-loop-change` (branch → verify → commit → PR) rather than committing + directly, per this repo's convention. + +## Do not + +- Do not create a skill for a one-off — if it won't recur, it belongs in the run's `LOG.md`, not a + skill. Promote to a skill once it repeats (that's the `review-signals` pattern). +- Do not write a vague `description` — a skill that doesn't say *when* to use it silently never + triggers, which is worse than not existing. +- Do not duplicate an existing skill's territory; extend the incumbent instead. +- Do not embed deterministic logic (parsing, validation, dispatch) as prose steps when it could be + tested code the skill calls. +- Do not forget the `CLAUDE.md` registration and `LOG.md` line — an unregistered skill is hard to + discover. diff --git a/CLAUDE.md b/CLAUDE.md index a2fb3b4..0fe747f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,8 +22,10 @@ know before touching code.}} - `knowledge/` — the shared memory loops read and write between runs (`signals/`, `notes/`, `domains/`). Read `knowledge/README.md` once; it's short. - `.claude/skills/` — `new-loop` (scaffold a domain), `ship-loop-change` (verify-before-ship), - `review-signals` (promote piled-up signals), and generic GitHub playbooks `github-cli-setup` - (session/scope checks) and `github-project-tracking` (milestones + issues + Projects board). + `review-signals` (promote piled-up signals), `write-skill` (scaffold a new skill in the house + style), and generic GitHub playbooks `github-cli-setup` (session/scope checks) and + `github-project-tracking` (milestones + issues + Projects board). The rule for skill vs. note vs. + code is in `knowledge/notes/skill-vs-note-vs-code.md`. - `LOG.md` — the global activity feed. Append one line here right before you commit a bulk of work from any loop run. diff --git a/LOG.md b/LOG.md index 75a3e6d..c63aa88 100644 --- a/LOG.md +++ b/LOG.md @@ -8,6 +8,7 @@ Format: `YYYY-MM-DD HH:MM | domain | one-line summary | link(s)` ## Entries +- 2026-07-26 23:05 | scaffold | documented the skill system: skill-vs-note-vs-code taxonomy note, write-skill meta-skill, github-project-tracking case study, and a README Skills index | [[knowledge/notes/skill-vs-note-vs-code.md]] - 2026-07-26 22:51 | scaffold | added github-cli-setup + github-project-tracking skills (generic GitHub playbook: gh account/scope checks, milestones/issues/Projects-v2 board) | [[.claude/skills/github-project-tracking/SKILL.md]] - 2026-06-22 16:00 | scaffold | stress-tested the orchestration/execution decision rule against opposite-shape domains (event+engine, scheduled+no-engine); rule held, fixed an implicit correlation in docs/loop-engineer-pattern.md's examples | [[docs/loop-engineer-pattern.md]] - 2026-06-22 15:00 | review-signals | added review-signals skill + skill-writing recipe; dogfooded against a synthetic signal (correctly judged "leave open," then removed) | [[.claude/skills/review-signals/SKILL.md]] diff --git a/README.md b/README.md index b5fdbe3..a17a0d0 100644 --- a/README.md +++ b/README.md @@ -97,15 +97,39 @@ knowledge/ CLAUDE.md template every session reads — fill in the {{PLACEHOLDER}}s for your project LOG.md global one-line-per-run activity feed .claude/skills/ - new-loop/ scaffold a new knowledge/domains//README.md - ship-loop-change/ verify (test/lint), then commit + PR — never ship unverified - review-signals/ periodically promote signals that have built up enough evidence to act on + new-loop/ scaffold a new knowledge/domains//README.md + ship-loop-change/ verify (test/lint), then commit + PR — never ship unverified + review-signals/ periodically promote signals that have built up enough evidence to act on + write-skill/ scaffold a new skill in the house style, then register + log it + github-cli-setup/ pre-flight the gh session: right account, repo visibility, token scopes + github-project-tracking/ turn a roadmap into milestones + issues + a Projects (v2) board ``` Copy either example domain as a starting point, or run the `new-loop` skill to scaffold a blank one. Triggers (cron/webhook) aren't reimplemented here — wire a domain's cadence to Claude Code's own `/schedule` or `/loop` skill; see [`docs/loop-engineer-pattern.md`](docs/loop-engineer-pattern.md). +## Skills + +The `.claude/skills/` directory is the reusable-procedure catalog — each is a `SKILL.md` an agent +follows when its `description` matches the moment. Some drive this template's own loop workflow; +others are generic playbooks (like the GitHub ones) that any project built from the template +inherits. The rule for what becomes a skill vs. a `knowledge/notes/` note vs. tested code is in +[`knowledge/notes/skill-vs-note-vs-code.md`](knowledge/notes/skill-vs-note-vs-code.md); use +`write-skill` to add a new one in the house style. + +| Skill | What it does | +|---|---| +| [`new-loop`](.claude/skills/new-loop/SKILL.md) | Scaffold a new `knowledge/domains//` charter for a loop. | +| [`review-signals`](.claude/skills/review-signals/SKILL.md) | Promote signals that have built up enough evidence into notes or backlog items. | +| [`ship-loop-change`](.claude/skills/ship-loop-change/SKILL.md) | Verify (lint/type/test) → commit → PR. Never ship unverified. | +| [`write-skill`](.claude/skills/write-skill/SKILL.md) | Scaffold a new skill in the house style, then register and log it. | +| [`github-cli-setup`](.claude/skills/github-cli-setup/SKILL.md) | Pre-flight the `gh` session: right account active, repo visible, token scopes present. | +| [`github-project-tracking`](.claude/skills/github-project-tracking/SKILL.md) | Turn a roadmap into milestones + issues + a Projects (v2) board. | + +For a worked example of the GitHub skills on a real project, see +[`knowledge/notes/case-study-github-project-tracking.md`](knowledge/notes/case-study-github-project-tracking.md). + ## Using this as a template Click **"Use this template"** on GitHub, or: diff --git a/knowledge/notes/case-study-github-project-tracking.md b/knowledge/notes/case-study-github-project-tracking.md new file mode 100644 index 0000000..b263001 --- /dev/null +++ b/knowledge/notes/case-study-github-project-tracking.md @@ -0,0 +1,52 @@ +--- +title: "Case study: scaffolding a project roadmap with github-project-tracking" +type: note +domain: [] +status: adopted +links: [[skill-vs-note-vs-code]] +--- + +A worked example of the `github-project-tracking` and `github-cli-setup` skills on a real project, +kept as provenance: it shows the skills doing end-to-end work, and it's where the skills were +generalized *from* (the reusable version was extracted after doing this once by hand). + +## What happened + +Starting point: a written architecture/roadmap for a mobile app, with the work already divided +into six phases (M0–M5). Goal: make that roadmap trackable on GitHub instead of living in a doc. + +The run, in order: + +1. **`github-cli-setup` first.** `gh auth status` showed two logged-in accounts; the one that + *owned* the target repo wasn't the active one, and its token was missing the `project` scope. + Switched accounts, and — because scope grants are interactive — handed the user the exact + `gh auth refresh -s project` command to run. This is precisely the failure the skill exists to + front-load: without it, the board step would have died halfway through. +2. **Milestones.** Six milestones (M0–M5) created via `gh api`, one per roadmap phase. Only needs + `repo` scope, so this ran before the `project` scope was even granted. +3. **Issues.** 24 task issues created with `gh issue create --milestone`, each body pointing back + at the roadmap section it came from, so an issue is self-explanatory without the doc. +4. **Board.** A Projects (v2) board created, linked to the repo, all 24 issues added, and each set + to `Todo` — laid out by Status for day-to-day work. + +## What this validated about the skills + +- **The scope split is real and load-bearing.** Milestones and issues (18-plus artifacts) were + created under `repo` scope while the board waited on an interactive `project`-scope grant. + Blocking everything on `project` would have stalled the whole run for no reason. +- **A 404 meant "wrong account," not "no repo."** The private repo was invisible to the initially + active account; the reflex to treat a 404 as "doesn't exist" would have been wrong. This lesson + is now written into `github-cli-setup`'s "Do not." +- **Eventual consistency is observable.** Right after bulk-adding, the board's item *count* lagged + the actual items. Verifying by listing issue numbers (not trusting the count) is now a step in + `github-project-tracking`. + +## Reusable takeaway + +The general shape — *check the session → create the cheap-scope artifacts → grant the extra scope → +create the expensive-scope artifacts → set initial state → verify by enumeration* — is what got +lifted into the two skills. Doing it once by hand, then extracting the skill, is the intended path +(see [[skill-vs-note-vs-code]]: promote to a skill once it recurs, not on the first occurrence). + +## Timeline +- 2026-07-26 | created — recorded the first end-to-end run that the github-* skills were generalized from diff --git a/knowledge/notes/skill-vs-note-vs-code.md b/knowledge/notes/skill-vs-note-vs-code.md new file mode 100644 index 0000000..91d8958 --- /dev/null +++ b/knowledge/notes/skill-vs-note-vs-code.md @@ -0,0 +1,61 @@ +--- +title: When to write a skill vs. a knowledge note vs. code +type: note +domain: [] +status: adopted +links: [] +--- + +This template gives an agent three different places to put something it figures out. Choosing the +wrong one is the most common way the system rots: reusable procedures get buried in chat, one-off +facts get promoted to skills nobody triggers, and logic that belongs in tested code ends up +re-derived in prose every run. This note is the decision rule. + +## The three homes + +| You have… | It goes in… | Because | +|---|---|---| +| A **repeatable procedure** — "when X, do these steps" | a **skill** (`.claude/skills//SKILL.md`) | Skills are *instructions an agent follows*. They're triggered by a description match and re-run the same way each time. | +| **Durable knowledge** — a decision, an analysis, something learned that should outlive the task | a **note** (`knowledge/notes/.md`) | Notes are *things that are true*, read by a human or agent for context. They don't "run." | +| **Deterministic logic** — parsing, control flow, anything with a right answer you can test | **code** (`src/`) | Code is *executed, not interpreted by a model*. If it can be unit-tested, it shouldn't live in a prompt. | + +## The decision rule + +Ask, in order: + +1. **Does it run the same way every time and can I write a test for it?** → **code.** Model + tokens are the wrong tool for deterministic work (JSON parsing, date math, dispatch). Put it in + `src/` behind a test. Skills and notes *call* code; they don't reimplement it. +2. **Is it a procedure an agent should follow when some trigger fires?** → **skill.** The tell is + that you can write a `## Steps` list and a `description` that says *when* to use it. If you find + yourself re-explaining the same steps to the agent across sessions, that's a missing skill. +3. **Is it a fact, a decision, or something learned — true whether or not anyone acts on it?** → + **note.** The tell is there are no "steps," just "here's what's true and why." Decisions + especially: capture what was chosen *and what was rejected and why*, so it isn't relitigated. + +## Boundary cases (where it's tempting to get it wrong) + +- **A skill that hardcodes a fact** → split it. The procedure is the skill; the fact it depends on + is a note the skill *reads*. Otherwise the fact is invisible to everything except that one skill. +- **A note that lists steps** → that's a skill wearing a note's clothes. If the point is "do this," + it's a skill, even if you also want prose around it. +- **A skill re-deriving logic every run** (parsing output, validating a schema in prose) → that + logic wants to be code the skill calls, so it's tested once instead of improvised each run. +- **"It's just this once"** → then it's neither; leave it in the run's `LOG.md`/Timeline. Promote + to a skill or note only when it recurs (this is exactly what `review-signals` is for). + +## Options considered, and why not + +- **One folder for everything ("just markdown").** Rejected: losing the skill/note distinction + loses the trigger. Skills are found by description-match at the moment they're needed; notes are + read for context. Collapsing them means either everything tries to "run" or nothing does. +- **Everything as a skill.** Rejected: notes don't have a trigger or steps, and forcing a `## Steps` + shape onto a decision record makes it worse to read and tempts re-running something that + shouldn't run. +- **Put procedures in code too.** Rejected for *agent* procedures: the value of a skill is that a + model adapts the steps to context (which files, which account, which repo). Hardcoding that in + Python removes the judgment that made a skill the right tool. Deterministic sub-steps still drop + down into code the skill calls. + +## Timeline +- 2026-07-26 | created — codifying the skill/note/code split after the knowledge base grew to five skills, so new artifacts land in the right home