v1.13.0: the kit takes over its own repository configuration
Released 2026-08-20. Two commits, one new skill: setup-repo, which writes the labels, issue forms
and repository settings that profile-repo had only ever been able to read.
What we were trying to fix
The lifecycle skills assume a repository is configured a particular way. create-issue files against
a label taxonomy on four axes. implement-issue reads the issue forms’ Area dropdown.
merge-pr assumes squash-only merges and delete-branch-on-merge. auto-dev sorts a backlog by an
effort label that has to exist.
All of that was read by get-repo-profile (as profile-repo was then called) and written by a human
clicking through the GitHub web interface. Which meant two things. Porting the kit to a second
repository was an afternoon of manual setup nobody wrote down. And once configured, the settings
drifted, silently, because the intended state existed only in whoever had clicked it.
What we decided
Split the concern in half and ship the missing half.
setup-repo is deterministic and idempotent: plan prints the drift between a declared manifest and
the live repository, apply converges it
(#192). At this version it covers the
label taxonomy, the issue forms under .github/ISSUE_TEMPLATE/, and the repository settings the
merge flow depends on. The manifest is the intended state, checked into the repository, so drift
becomes visible rather than merely present. The four surfaces a public repository is judged by, its
description, homepage, topics and Pages source, were still unmanaged here and only joined the
manifest much later, in v2.1.0
(#400).
Then the kit ran it on itself (#196), adopting its own label taxonomy and issue forms through the tool rather than by hand, which is the only way to find out whether the tool works.
The reader and the writer stayed separate skills on purpose, later recorded as
ADR 0013.
profile-repo observes and never writes; setup-repo writes and is the only thing that does. A
single skill doing both would have made every profile refresh a potential mutation of the repository
it was describing.
What got cut
--prune was left out. setup-repo apply converges what the manifest declares and never deletes a
label the manifest does not mention, so a repository with its own extra labels keeps them. A tool
whose first run can delete labels across an unfamiliar repository is a tool nobody runs twice.
The shipped templates/repo-setup.yml also keeps its area: <your-area> placeholder rather than the
kit’s real area names. This was the one amendment the owner made to the plan on the day it was
implemented: the kit’s own areas are per-skill names like area: merge-pr, which are meaningless in
a consumer’s repository, so they live in a repo-local .github/repo-setup.yml override and the
shipped default stays a placeholder. The suite asserts the shipped manifest declares all three axes,
and the placeholder satisfies that, so it is deliberately not something to “fix”.
What bit us
Nothing in the release itself, which is what two commits and a new skill usually buys you. The bill arrived in the next one.
setup-repo’s plan passed on placeholder area names instead of failing on them
(#198), which is the exact defect the
placeholder decision above made reachable and which nobody thought to check for on the day. And a
refused label write did not name the status it had observed
(#200), so a refusal told you that
something had gone wrong without telling you what GitHub had actually answered. Both landed in
v1.14.0.
The pattern is the one this whole era keeps re-teaching: a new writer is easy, and making its refusals say what they saw is the part that gets skipped.