← all pages

Reference · 02

The skill tree

Twenty skills run the machine. Each one is here because something in the system references it — and for no other reason.

Admission by reference

The tree had grown to twenty-eight skills, and a census showed what growth without a rule produces: six skills nothing referenced anywhere, one vendored skill accounting for 61% of the repo's lines with no in-repo dependents, three manifest rows pointing at folders deleted weeks earlier. Nothing was wrong with any individual skill. What was missing was a test for whether a skill belongs.

The test is mechanical: a skill lives in the tree if, and only if, something in the system references it — another skill, a seeded doc, a runner's prompt, or a cron. A skill that is merely useful goes to a personal library instead. Usefulness is not membership, and "we might want it someday" is the exact argument the rule exists to refuse. Applying it cut the tree to twenty-two, and the version after that to twenty.

The tree

ClassSkillsAdmitted because
Spine stages & entries grill-me wayfinder to-spec to-tickets triage implement tdd code-review ship Each is a stage of the machine
Invoked by the spine domain-modeling research prototype diagnosing-bugs resolving-merge-conflicts codebase-design improve-codebase-architecture A spine skill calls them by name
Reference skills writing-for-agents The single home of an org-wide fact, consumed as $name by other skills
Setup and shorthand setup-engineering-workflow grill-me-with-docs symphony-run Seeded per-repo configuration, and the entries a human or a runner types

The seam rule

Every fact a skill needs is placed by where it varies. Varies per repo → a seeded doc in that repo, written by the setup skill. Shared across the org → a reference skill. Varies per machine or runner → the runtime that owns it, whether that is a dispatcher's config or a personal agent library. Skills are interfaces; a skill carrying a fact from the wrong class is misplaced configuration wearing a skill's clothes. The reference class is the narrowest of the four, and it has since shrunk to one member — see below.

The rule predicts things. When the stuck column was renamed on the board, the rename touched four repos' configuration files and zero skills — exactly what placement-by-variance says should happen, because a column's name varies per tracker and no skill should ever have held it.

What the cut taught

The last two turned out to be the same mistake, and the next version undid both.

What version four corrected

Three faults traced back to one cause. Unattended runs stalled on tickets carrying no plan and none of the facts triage had verified. Grilling sessions jumped straight to specs, because the placement rule in writing-for-humans redefined a grilling session's output as a brief. And repos accumulated an effort-agnostic decisions file that grew without bound, because it was the only home a grilling record had. In each case a Redkale-wide doctrine sat in a reference skill that every session re-read, and the indirection through $brief and $writing-for-humans quietly changed what the calling skill meant.

So the doctrine moved to where it is read once: the files the setup skill seeds into each repo. The tracker instructions now carry how to write on that tracker and what a ready ticket contains — the five evidence kinds and the follow-up shape included — and a new artefact document names where the effort's long-form record lives, seeded from three hosts: a file in the repo, a Claude artefact, a published site. Every engineering skill opens with one sentence pointing at the tracker instructions, and the flow skills shrank below their upstream size while the seeds grew.

ChangeSkillsWhy
Deletedbrief evidence writing-for-humansEach held doctrine that belongs in the per-repo seeds, where a session reads it once
Renamedgrilling → grill-me, grill-with-docs → grill-me-with-docsBack to upstream's split, so the drift we own is the content and not the names
Renamedmerge-and-deploy → shipThe verb the board's Ship state already named. Its delivery seed folded away with it: close-out facts became bullets in the repo's agent-skills block
Addedsymphony-runThe dispatcher's lane, moved out of the runner's prompt — the lane names skills, so it belongs in the same versioned unit as the skills it names

Evidence did not stop existing; it stopped being a skill. It is the closing paragraph of implement, produced in a sub-agent with fresh context that was not part of the session that wrote the code — which is what "the judge sits outside the system under test" always required. A separate context, not a separate skill.

The quiet rule underneath: the tree is derived from the process, so its size is a consequence, not a target. If the process grows a stage, the tree grows a skill; nothing else grows it.