# Recipe — rename a federation sibling library

> **Audience:** maintainer renaming an `mgf-*` sibling on the devpi index / Codeberg repo / disk.
> **Closes:** PAPER-79 — the rename surface was previously rediscovered each time as ad-hoc sed scripts in some `.claude/settings.local.json`.
> **History:** Codified 2026-05-27 after the `mgf_common → mgf-common` (separator) and `mgf-ubs → mgf-hrb` (whole-name) renames showed the same surfaces leak the same way every time.

---

## When to use this recipe

You're renaming a federation sibling when **any** of these is true:

- The distribution name is changing (separator drift `mgf_x → mgf-x`, or domain rename `mgf-ubs → mgf-hrb`). This is the name published to the devpi index (per [PKG-01/PKG-10](../standards/PACKAGE_DISTRIBUTION.md#PKG-01); `mgf-*` are published to and resolved from the devpi index, not pypi.org).
- The Codeberg repo slug is changing (mirrors the dist-name per NM-01).
- The import path (`mgf.<name>`) is changing — rare; typically only when the dist-name moves with it.

If only the import path moves while the dist-name stays put, see the `mgf-fed migrate` codemod (`docs/standards/RELEASING.md` §3.1) — that's a single-package surgery, not a federation rename.

---

## The rename touches eight surfaces

Renames leak long-tail drift because they hit surfaces that don't share a search index. The full list, in the order to sweep them:

```
1. The sibling itself          — pyproject.toml [project].name; src/<old>/ → src/<new>/
2. devpi index                 — publish under the new name (PKG-01/PKG-10); no PyPI/squat-reserve step needed (see step 3)
3. Codeberg repo               — repo rename + redirect; old URL stays valid via Codeberg's auto-redirect
4. mgf-common federation refs  — _FEDERATION_SIBLINGS, FEDERATION.md §5, DEPS.md, MGF_ADOPTION.md
5. Every consumer's pyproject  — [project.dependencies] + [project.optional-dependencies]
6. Every consumer's [tool.uv.sources] — local editable path (./mgf_x → ./mgf-x)
7. Every active venv           — _editable_impl_<old>.pth (silent footgun; see PAPER-78)
8. Local filesystem            — PycharmProjects/<old>/ husk + ARCH/<old>/ archive husk
```

Skip any one of these and someone discovers it weeks later as `ModuleNotFoundError` or `uv sync` failing on a non-existent path.

---

## Step-by-step checklist

### Phase A — Plan + announce (before any code change)

1. **Pick the new name.** It MUST follow [NM-01..NM-04 in `docs/standards/NAMING.md`](../standards/NAMING.md): PyPI/Codeberg/local-dir use hyphens (`mgf-<sibling>`); import path uses dots (`mgf.<sibling>`); dist-name and Codeberg slug are byte-identical.

2. **Open a federation-wide notification.** Per REL-09, every consumer needs a notification. Open a single tracking entry in `mgf-common/FEEDBACK.md` (severity 🟡 High) naming the old + new name + the cutover date.

3. **Old-name handling (no reserve step needed).** `mgf-*` are published to and resolved from the **private** self-hosted devpi index (`magogi/prod`) ([PKG-01](../standards/PACKAGE_DISTRIBUTION.md#PKG-01)) — not the public pypi.org index — so there is **no public squatting risk** and no need to publish a tombstone release reserving the old name. A separator-only rename needs nothing here regardless: devpi normalises `mgf_x` and `mgf-x` to the same project per PEP 503, exactly as PyPI does ([PKG-10](../standards/PACKAGE_DISTRIBUTION.md#PKG-10)). (Historically, on pypi.org a whole-name rename meant shipping a final "renamed to <new>" tombstone to block a future squatter; on the private devpi index that step is obsolete.)

### Phase B — The sibling itself

4. **Sibling's `pyproject.toml`:** rename `[project].name` from old → new. If the dist-name is changing (not just a separator), also bump the version's PATCH (e.g., `0.4.2 → 0.4.3`) so adopters can distinguish "the version that's still the old name" from "the version that landed under the new name."

5. **Sibling's source tree:** rename `src/<old>/` → `src/<new>/` only if the IMPORT PATH is changing. Pure dist-name renames (e.g., separator drift) leave the import path stable.

6. **Sibling's CHANGELOG.md:** add a `## [<new-version>] — <date> — renamed from <old>` section. Cross-reference the rename's FEEDBACK entry. Per REL-01, this commit MUST be the tagged release commit.

7. **Sibling's README / DEPS.md / MGF_ADOPTION.md:** sweep for stale `<old>` references. Ruff / grep / global-search-replace; the file count is small (typically <10 surfaces inside the sibling itself).

### Phase C — mgf-common federation refs

8. **`src/mgf/common/cli/_agents.py`:** update the `_FEDERATION_SIBLINGS` constant (one line; per PAPER-80 Approach B this constant drives the AGENTS_BRIEFING enumeration via f-string interpolation). The pin test for `_agents` + `STARTHERE.md` parity catches divergence.

9. **`STARTHERE.md` line 42-46:** mirror the same list. The `test_agents.py` parity test enforces this stays in sync with `_FEDERATION_SIBLINGS`.

10. **`FEDERATION.md` §5:** update the "need X → use Y" table.

11. **`DEPS.md`:** update any row that names the renamed sibling.

12. **`docs/standards/`:** grep for the old name in every standards doc; sweep stale references. Common surfaces: `NAMING.md` (historical examples), `FEDERATION.md` (catalog), any standard that names siblings explicitly.

13. **`docs/cutover/`:** per REL-06's release flow, this rename is a candidate for a per-release cutover doc that walks consumers through the touch-points below.

### Phase D — Consumer-side sweep (per consumer)

14. **`<consumer>/pyproject.toml`:** rewrite `[project.dependencies]` and `[project.optional-dependencies]` entries. `mgf-fed catch-up` (post-PAPER-79 follow-up) audits the pin name; manual sed works in the interim:

    ```bash
    sed -i 's/^\("mgf-old-name/"mgf-new-name/g' pyproject.toml
    ```

15. **`<consumer>/pyproject.toml::[tool.uv.sources]`:** the local-path entry. Per PAPER-83's `_check_uv_sources_paths` audit, `mgf-fed catch-up` flags broken paths post-rename; `--apply` rewrites separator-drift cases unambiguously. Whole-name renames need manual edits.

16. **Active venv's `_editable_impl_<old>.pth`:** the silent footgun (root cause of PAPER-78). Either:
    - `uv sync --reinstall` (regenerates the `.pth`), OR
    - `pip install -e .` (overrides the stale `.pth`), OR
    - Manually edit `.venv/lib/python*/site-packages/_editable_impl_<old>.pth` to point at the new path AND rename the file to `_editable_impl_<new>.pth`.

17. **Local filesystem husks:** `~/PycharmProjects/<old>/` and `~/PycharmProjects/ARCH/<old>/` often survive renames as empty directories carrying only `.claude/settings.local.json` + `.idea/`. Delete them — they cause confused future agents to re-clone into the old name. `rm -rf ~/PycharmProjects/<old>` (verify it's empty of source first via `find <path> -type f -not -path '*/.*'`).

18. **Verify per consumer:** `uv sync --all-extras && mgf-fed catch-up && pytest -q`. The catch-up + pytest combo catches almost every residual surface.

### Phase E — Notification + closeout

19. **Update the FEEDBACK entry** (from step 2) to ✅ SHIPPED with a retrospective listing the touched surfaces + any pitfall discovered.

20. **Update consumer-side `MGF_STANDARDS_CONFORMANCE.md`** in each consumer if the rename affected a row that names the sibling explicitly.

---

## Composes with future work

This recipe will get a CLI helper when [PAPER-79 Approach B](../../FEEDBACK.md#paper-79--no-federation-aware-rename-a-sibling-library-recipe-or-cli-helper) lands — `mgf-fed migrate-sibling <old> <new> [path]` that mechanises steps 14-17. Approach C (federation registry) makes the rename a one-row edit that drives every downstream surface from a single source-of-truth.

Until the helper exists, this recipe is the answer when an agent or maintainer asks "how do I rename a sibling?"

---

## Cross-references

- [`docs/standards/NAMING.md`](../standards/NAMING.md) — NM-01..NM-04, the naming convention that gates step 1.
- [`docs/standards/PACKAGE_DISTRIBUTION.md`](../standards/PACKAGE_DISTRIBUTION.md) — PKG-01/PKG-10, why the new name publishes to the private devpi index (not pypi.org) and why the old-name reserve step is obsolete (step 3).
- [`docs/standards/RELEASING.md`](../standards/RELEASING.md) §7 — REL-09 consumer-notification rule that gates step 2.
- [`FEEDBACK.md` PAPER-78](../../FEEDBACK.md#paper-78) — the editable `.pth` silent-footgun that step 16 fixes.
- [`FEEDBACK.md` PAPER-79](../../FEEDBACK.md#paper-79) — this recipe's parent; Approach B + C are the mechanised follow-ups.
- [`FEEDBACK.md` PAPER-83](../../FEEDBACK.md#paper-83) — the `[tool.uv.sources]` audit that catches step 15 drift.
