Tagout

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

  1. Two steps could only be done after the merge: the engine extract against the branch config and the post-merge check.