v4.0.0: profile-repo and setup-repo become init, and the bench learns to measure it
Released 2026-10-10. One breaking change, four features and five fixes, plus the docs and chore commits that rode along.
What we were trying to fix
Three themes.
Making a repository ready took two skills and two commands. profile-repo records a
repository’s facts in .claude/skills/repo-profile.md, and setup-repo converges labels, issue
forms, settings, topics and the Pages source from a manifest. ADR 0013 kept them apart and named the
shape to take if the boundary kept confusing users: a merge, in the next major. This is that major.
A diff a revert cannot undo got the same review as any other. A pull request that crosses a
migration, a send to an external party, a deletion of user-owned data or a plugin manifest is a
one-way door, and auto-dev would land it like the rest (#694, fixed by #696).
Two small gaps in the plumbing. The tracker dispatcher already resolved the profile’s tracker
detail and handed a backend only half of it, so azure-devops.sh read the committed profile a
second time on every call (#693, fixed by #705). The roseline gate’s denial did not say how to proceed, and a repo
holding only a .slnx could not be opened by Roseline discovery at all (#699, fixed by #706).
What we decided
init is the one repository-setup skill (issues #701, #702 and #703, landed as #704, #707 and #709). It runs profile, plan, apply and
refresh in a single command. The four profile and setup scripts and their two references moved under
skills/init/ as a pure git mv that kept mode 100755 (#707), and then skills/profile-repo/ and
skills/setup-repo/ were deleted with no alias (#709, ADR 0012). The six apply rules from
setup-repo now live in skills/init/references/desired-state.md, so the link that pointed at them
still resolves. ADR 0018 supersedes ADR 0013 and records the merge. The full run is /tagout:init,
and the profile alone is /tagout:init --profile-only [--refresh].
The command is typed /tagout:init because a bare /init in Claude Code runs the built-in
CLAUDE.md generator. A review finding on #709 moved the NO_PROFILE remedy, the profile header
and the AGENTS.md routing row to the prefixed form.
A one-way-door diff is now reviewed at high and carries a ### One-way door section, and
auto-dev holds that pull request under a new ## Held for owner state section instead of landing
it (#696). The dispatcher exports TRACKER_DETAIL beside TRACKER_REPO, and azure-devops.sh
reads it first and falls back to its own profile read only on a direct call (#705). The roseline-gate denial now names the tools as
installed, passes the file’s nearest .csproj as project:, and fails open on a .slnx-only repo (#706).
What got cut
The 15 should-trigger queries from the two retired eval sets did not come across in #709. The contract checker refuses a contract larger than the measured result, and refreshing the result is an owner-run bench under ADR-0007, so they waited for #717. Renaming the ADR file was also left alone, because it would rewrite history.
What bit us
The trigger bench could not measure init. A bare Skill(skill="init") is also what Claude
Code’s built-in /init calls, so #714 made the eval and harvest.py refuse a bare init. But
run_all.py stages the skill under .claude/skills/init/, so the bench only ever sees the bare
name. Every positive scored a miss, and the first bench run on unfixed main was refused:
REFUSED [init]: recall 0.0 beside specificity 1.0 over 30 positives. #716 made _names_match
accept a bare init again while still refusing another plugin’s <plugin>:init, and
tests/evals-stage-skills/test.sh now pins the truth table. harvest.py kept the stricter rule,
since it reads installed-plugin sessions, where the prefix exists.
With the bench working, #717 folded the 15 queries into evals/init-trigger-eval.json, pruned the
orphaned profile-repo and setup-repo results and their baseline.json entries, and refreshed
evals/results/init.json. The measure is [init] 25/39 recall=0.533 specificity=1.0. On the
earlier 24-query set it was recall 0.67 and specificity 1.0. Recall fell because the folded queries
are the harder ones, several of them contested between the two retired skills, such as why does
auto-dev ignore my effort ordering? and turn on auto-delete for merged branches. That is a
finding about the description of init, not a regression.
A Renovate pull request could not pass the kit’s own check. #665 bumped templates/ci-dotnet.yml
and left its generated copies under plugins/ alone, so kit refused the drift and no bot can run
host-adapters build. The supervisor regenerated the copies by hand. #711 makes Renovate manage the
copies too, so source and copies move in one branch, adds a static assertion to
tests/renovate-config/test.sh that each copy path is reachable, and records the contract in ADR
- Two steps could only be done after the merge: the engine extract against the branch config and the post-merge check.