# Migration from `mgf-usb` to `mgf-hrb`

> **Supersession statement.** `mgf-hrb` (this library) replaces
> the predecessor project `mgf-usb`. The `mgf-usb` repository
> was deleted 2026-05-27 once its lessons were folded into this
> design — there is no `mgf-usb` codebase to migrate FROM in a
> mechanical sense. This document exists as the historical record
> of the supersession + the "if you have `mgf-usb` pinned in your
> pyproject, here's the modern replacement" pointer.
>
> **Closes FEEDBACK paper [`DOC-02`](FEEDBACK.md#doc-02--supersession-relationship-to-mgf-ubs-is-not-declared-in-any-user-facing-doc).**

---

## Naming — one source of confusion, pin it now

Three near-identical names appear in federation discussion. The
disambiguation table is the entire mental model you need:

| Name | What it refers to | Status |
|---|---|---|
| **`mgf-usb`** | The predecessor PROJECT. Was a standalone Python library — v0.1 → v0.2.5 of the userspace hardware-broker work, USB-only. | **Deleted 2026-05-27.** Lessons folded into `mgf-hrb`. No repo, no PyPI, no consumers expected to remain on it. |
| **`mgf-hrb`** | The replacement PROJECT (this library). | Active. You're reading this file inside it. |
| **`mgf-hrb-usb`** | A WORKER SUBSYSTEM *inside* `mgf-hrb`. Per-bus implementation of the broker's USB-specific behaviour. | Designed in `hrb-design/mgf-hrb-usb-worker.md`; ships in phases per [`USB-02`](FEEDBACK.md). The first phase (Slice A — discovery only) is the active next-up work item. |

The `mgf-hrb-usb` worker is a SUBSYSTEM of this library — it is
NOT the deleted predecessor `mgf-usb`. The names look almost
identical; keep this table mentally pinned for the rest of the
federation rename's lifespan.

---

## Why the rename + why the predecessor was deleted

`mgf-usb` was the v0.1 – v0.2.5 line of the userspace hardware-
broker work — single-language Python, single-bus (USB) focus,
the proving ground for the identity-continuity comparator
([`MODEL-01`](FEEDBACK.md)) and the early USB-worker lessons.

`mgf-hrb` is the rewrite that generalises along three axes
simultaneously:

| Axis | `mgf-usb` (deleted) | `mgf-hrb` |
|---|---|---|
| **Buses** | USB only | PCIe + USB + (future) CPU/memory + GPU |
| **Language split** | Python only | Zig below the socket (enforcement, hot path); Python above it (SDK, tooling) — zero FFI |
| **Posture** | direct kernel access | userspace broker with capability gates + leases + ghost-free revoke (G3) + the G4 survivability dividend |

The predecessor's repository was deleted once the architectural
lessons were captured in `hrb-design/` and the comparator's logic
was ported byte-equivalent to `hrb-code/src/identity.zig` +
`src/mgf/hrb/identity.py`. Keeping a dead repo around invites
consumers to pin against it; deleting it forces the conversation
to land here.

---

## What was carried forward

The substantive value of `mgf-usb` lives on inside `mgf-hrb` in
these forms — if you had code consuming the predecessor, look
here for the equivalent:

| `mgf-usb` concern | `mgf-hrb` equivalent | Where it lives |
|---|---|---|
| Identity-continuity comparator (the `same_likely` family) | `mgf.hrb.identity` — Python mirror of the canonical Zig at `hrb-code/src/identity.zig`. Byte-equivalent algorithm + weights; the iFig DFU scores (11 / 13 / 15) are pinned by `tests/unit/mgf/hrb/test_identity.py`. | `src/mgf/hrb/identity.py` |
| Sysfs USB-device field gathering | `mgf.hrb.sysfs.snapshot_from_sysfs(syspath)` — stdlib-only helper that reads the standard sysfs files (`idVendor` / `idProduct` / `busnum` / `devpath` / `serial`) and returns a comparator-ready `Snapshot`. | `src/mgf/hrb/sysfs.py` (FEEDBACK [`SDK-07`](FEEDBACK.md)) |
| USB-worker design lessons | `hrb-design/mgf-hrb-usb-worker.md` — the full design that `mgf-hrb-usb` (the worker SUBSYSTEM in this library) implements per [`USB-02`](FEEDBACK.md). Tier-1 sysfs substrate, tier-2 usbfs, tier-3 netlink. | `hrb-design/mgf-hrb-usb-worker.md` |
| The "claim once, broker steps out" survivability dividend (G4) | Did not exist in `mgf-usb`. NEW in `mgf-hrb`: lease + raw-channel via SCM_RIGHTS-passed fd; broker keeps lease tracking, the consumer gets full-speed direct USB access. | `Client.claim(urn).raw()`; recipe at [`recipes/use-a-broker-fd-with-libusb.md`](recipes/use-a-broker-fd-with-libusb.md) |
| Capability gates + ghost-free revoke | NEW in `mgf-hrb`. `mgf-usb` had direct access — no broker, no capabilities, no revoke story. | `hrb-design/mgf-hrb-complete-design.md` Part 3 (lease engine) + Part 6 (capabilities) |

The federation's principle 3 ("use the federation; do not
reinvent it") applies: if you find yourself reaching for code
that used to live in `mgf-usb`, check the table above for the
modern path before re-implementing.

---

## Adoption sequence for new consumers

If you're starting fresh and want to consume `mgf-hrb`'s value,
the order to adopt is:

1. **Adopt the comparator first.** `mgf.hrb.identity` is the one
   piece of `mgf-hrb` that's available today with no broker, no
   USB worker, no Zig integration — pure Python, stdlib only.
   Replace your in-line "is it the same device" logic with
   `same_likely(before, after)`. If your gathering layer is
   sysfs, use `mgf.hrb.sysfs.snapshot_from_sysfs()` to retire
   any hand-rolled sysfs parsing ([`SDK-07`](FEEDBACK.md)).
2. **Wait for [`USB-02`](FEEDBACK.md) Slice A.** Then switch
   discovery from your direct sysfs walk to
   `Client.list("hw:/usb/**")` + `Client.inspect(urn)`. Pure
   read; no behaviour change for your hot path.
3. **Wait for [`USB-02`](FEEDBACK.md) Slice B.** Then switch
   device claiming from your direct `libusb_open` / `usbfs`
   handle to `Client.claim(urn, ClaimMode.EXCLUSIVE)`. Use
   [`recipes/use-a-broker-fd-with-libusb.md`](recipes/use-a-broker-fd-with-libusb.md)
   to plumb the resulting fd through libusb-1.0; this is where
   the G4 survivability dividend lands.
4. **Wait for [`USB-02`](FEEDBACK.md) Slice C.** Then switch
   from polling to event-driven monitoring via
   `Client.monitor("hw:/usb/**")`.

Each step is a self-contained PR you can merge independently.

---

## Pre-flight checks before the broker flow

Before any broker `claim`, confirm no system daemon holds the
device — see [`USB-03`](FEEDBACK.md) (the rule + worked
example) and [`recipes/track-a-device-across-a-mode-change.md`](recipes/track-a-device-across-a-mode-change.md)
§0 (the script shape: `sudo systemctl stop <holder>`). This
matters most for iFig devices (`usbmuxd`) but the rule
generalises to any daemon-held device class.

---

## What this doc is NOT

- It's NOT a symbol-by-symbol mapping. `mgf-usb` was deleted;
  there's no `__all__` to enumerate. Match `mgf-hrb`'s public
  surface (in [`PUBLIC_API.md`](PUBLIC_API.md)) against what
  your code USED to do.
- It's NOT a deprecation timeline. The predecessor is already
  gone (deleted 2026-05-27, before this doc was written).
- It's NOT the federation-wide rename recipe. That belongs in
  [`mgf-common`'s PAPER-79](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/FEEDBACK.md);
  this doc is the consumer-facing migration half for THIS
  specific rename.

---

## Cross-references

- Federation rename pattern: [`mgf-common`'s PAPER-79](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/FEEDBACK.md).
- The supersession's filing paper: [`DOC-02`](FEEDBACK.md#doc-02--supersession-relationship-to-mgf-ubs-is-not-declared-in-any-user-facing-doc).
- Public API surface: [`PUBLIC_API.md`](PUBLIC_API.md).
- Wire-protocol design: [`hrb-design/mgf-hrb-complete-design.md`](hrb-design/mgf-hrb-complete-design.md) Part 8.
- USB worker design (the SUBSYSTEM, not the deleted predecessor): [`hrb-design/mgf-hrb-usb-worker.md`](hrb-design/mgf-hrb-usb-worker.md).
