setup-repo · git:20260831.455f701 · 2026-08-31 · sha256 898eabf2f18accac
setup-repo git:20260831.455f701A
Immutable. This exact content is served forever at /api/v1/blob/898eabf2f18accac.
--- name: setup-repo description: >- Bring a GitHub repository to the configuration the issue/PR lifecycle skills assume — label taxonomy, issue forms under .github/ISSUE_TEMPLATE/, repository settings (delete-branch-on-merge, squash-only merges) — deterministic and idempotent: `plan` prints drift, `apply` converges it. Use when a repo needs configuring or has drifted: "set up the labels", "create the issue templates", "turn on auto-delete merged branches", "configure this repository the way the kit expects", "why does auto-dev ignore my effort labels", « configure les labels du repo », « crée les templates d'issue », « supprime automatiquement les branches mergées ». It WRITES what get-repo-profile only READS. Does NOT file issues, implement code, or merge PRs. license: MIT compatibility: >- Requires git, python3 with PyYAML, jq, and an authenticated gh CLI. Without gh the label and settings surfaces are reported as refused and the run exits 3 with the local issue-form copy still applied. The settings surface additionally needs a token with admin rights on the target repository; without one it is refused by name rather than silently skipped. metadata: author: Philippe Matray suite: ai-migration-kit --- # Configure a repository for the lifecycle skills `create-issue`, `implement-issue`, `merge-pr` and `auto-dev` are generic workflows wrapped around a thin layer of repo-specific facts. `get-repo-profile` records those facts — and when it finds none, its only outlet is a `TODO:` line. That is the right answer for a fact it cannot read and the wrong one for a **configuration the repo does not have**, which is what four of its TODOs always are: | What the profile reports | What it actually means | What silently degrades | |---|---|---| | no `priority:` axis | the labels were never created | `create-issue` omits the axis | | no `effort:` axis | the labels were never created | `auto-dev`'s "small first, then medium" ordering has nothing to sort on | | no `area:` axis | the labels were never created | `auto-dev` cannot give parallel workers non-overlapping areas | | no `.github/ISSUE_TEMPLATE/` | the directory was never created | `create-issue` has no form to obey | This skill is the missing verb. It does not describe a repo; it makes one. ## Do this A bundled script does the deterministic work. Run it from anywhere in the target repo (it anchors to the git root). `<skill-dir>` is this skill's base directory — given when the skill loads: ```bash bash "<skill-dir>/scripts/repo-setup.sh" plan ``` `plan` writes nothing, so it is safe against a repository you only read. Show the operator the delta it prints, then converge: ```bash bash "<skill-dir>/scripts/repo-setup.sh" apply ``` Read the exit code — it is the report, and each value means one thing: | Exit | Meaning | What to do | |---|---|---| | 0 | converged | Say so. Nothing to do. | | 1 | `plan` found drift | Show the delta, then run `apply` — **except** a `!TODO` line: `apply` never creates a placeholder, so fill it into the manifest instead (#198). | | 2 | bad usage, or an unreadable/unparseable manifest | Fix the manifest; never partially apply. | | 3 | a surface was refused | Relay **which** surface and why — the report names it. The rest did land. | | 4 | not inside a git repository | Say so and stop. | ## The desired state `templates/repo-setup.yml` in the kit is the shipped default. A consumer repo overrides it by committing its own `.github/repo-setup.yml`, which `repo-setup.sh` prefers — so a consumer's taxonomy survives a kit upgrade. `--manifest <path>` overrides both. Four rules govern what `apply` will and will not do, and they are worth relaying to the operator before the first run against a repo that already has labels: - **Additive.** A live label the manifest does not declare is reported `!EXTRA` and **kept**. Only `--prune` deletes anything. A repo already running `P1`/`P2` must not have its taxonomy renamed out from under it. - **`pruneKeep` outranks `--prune`.** Labels a *tool* owns look undeclared because no human declares them, and deleting them breaks the automation that reads them. The manifest's `pruneKeep` globs — seeded with release-please's `autorelease: *` and Renovate's `dependencies` — are reported `!KEEP` and never deleted. Add the repo's own bot labels there before running `--prune` on it. - **Never clobber.** An issue form that already exists is reported `!SKIP`. A tuned form outranks the kit's default. - **A name in angle brackets is a placeholder** — never created, and reported `!TODO` **and counted as drift** on every run (`plan` exits 1), so an unfilled axis stays visible instead of looking converged (#198). The `area:` axis ships this way because it names the consumer's code, not the kit's: fill it in before `auto-dev` runs a fleet — `apply` will not resolve this one for you. ## Autonomy contract Run **hands-off**. `plan` is a read — no task list or precondition ceremony. Before `apply`, show the delta and get a yes when the repo is not the user's own or the run includes `--prune`; a straightforward `apply` on their own repo needs no gate. Never invent a taxonomy. If the manifest lacks an axis the repo needs, edit the **manifest** and re-run — an axis created by hand with `gh label create` is exactly the non-deterministic setup this skill exists to replace. When a surface is refused, report it and move on: a partially configured repo with a named gap beats an abort that leaves the operator guessing which half landed. ## Afterwards `get-repo-profile --refresh` — this skill's row in the hand-off table, and the reason for it: the four TODOs are facts now, so the profile records the real axes and the lifecycle skills start applying them. `plan` exiting 1 on drift makes it usable as a CI step, if the repo wants configuration drift to go red the way code drift does. ## Recap Close with the shared recap shape — [`../_shared/recap.md`](../_shared/recap.md). It owns the four blocks (verdict · **What happened** · **Artifacts** · **Assumed · skipped · unverified**, where `None` is a required answer rather than an omission) and the **Next** line, which is read off this skill's row in that file's hand-off table instead of being decided again here. Everything below is only what **setup-repo** adds on top of them. - Name each surface separately — labels, issue forms, repository settings — and whether it converged, was already converged, or was **refused** (and by what: missing admin rights, an unfilled `area:` placeholder, `gh` unauthenticated). A partially configured repo with a named gap is a result; an unqualified "done" over a refused surface is not. - Say whether `--prune` ran. It deletes labels, including the six undeclared GitHub defaults, so it is never a silent detail.