# v1.0 federation quality-gate sweep (Wave 4 / E2)

**Status:** Draft for maintainer review.
**Generated:** 2026-05-18 (post-Wave-3, mgf-common 0.37.0 + sibling minors).
**Owner:** mgf-common.
**Pairs with:** [`v1_0_stability_audit.md`](v1_0_stability_audit.md).

This is a *gate inventory*. Every entry is either a green check the maintainer
can sign off on, or a numbered blocker that must be resolved before v1.0.
The audit deliberately distinguishes blockers (v1.0 cannot ship until fixed)
from nits (carry forward into v1.0.1 / v1.1).

---

## §1 Artifact presence matrix

A name is "Y" if the artifact exists and has non-trivial content.

| Repo            | `PUBLIC_API.md` | `PUBLIC_API.json` | `docs/claude/` | `docs/cutover/` | `docs/standards/` | `CHANGELOG.md` | `FEEDBACK.md` | `tests/` | import-linter |
|-----------------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| mgf-common      | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| mgf-alembic     | Y | **·** | Y | Y | Y | Y | Y | Y | Y |
| mgf-apiprobe    | Y | **·** | Y | Y | Y | Y | Y | Y | Y |
| mgf-django      | Y | **·** | Y | Y | Y | Y | Y | Y | Y |
| mgf-fastapi     | Y | **·** | Y | Y | Y | Y | Y | Y | Y |
| mgf-http        | Y | **·** | Y | Y | Y | Y | Y | Y | Y |
| mgf-sqlalchemy  | Y | **·** | Y | Y | Y | Y | Y | Y | Y |

**Gap → Q-1:** Only mgf-common has a generated `PUBLIC_API.json` pin. The
six siblings rely on `PUBLIC_API.md` alone — there is no programmatic diff
test catching when their public surface drifts from the documented surface.
Recommend: port `tools/generate_public_api_json.py` to each sibling **before
each sibling cuts v1.0** (not necessarily before mgf-common v1.0).

---

## §2 Test sweep — federation (2026-05-18)

Each ran in its own `.venv` (sibling isolation):

| Repo            | Tests passed | Deselected | Wall-clock | Status |
|-----------------|-------------:|-----------:|-----------:|--------|
| mgf-common      | **1587**     |        13  |  15.86 s   | ✅      |
| mgf-alembic     | **102**      |        10  |   1.38 s   | ✅      |
| mgf-apiprobe    | **848**      |        20  |   0.61 s   | ✅      |
| mgf-django      | **54**       |         6  |   0.16 s   | ✅      |
| mgf-fastapi     | **152**      |         6  |  62.57 s   | ✅      |
| mgf-http        | **101**      |         5  |   0.40 s   | ✅      |
| mgf-sqlalchemy  | **41**       |         3  |   0.59 s   | ✅      |
| **Federation**  | **2885**     |        63  |  ~82 s     | ✅      |

**Verdict:** Federation test suite is green. No regressions from any Wave 1/2/3
change. This gate **passes for v1.0**.

---

## §3 Ruff sweep — federation

| Repo            | Status                                                                        |
|-----------------|-------------------------------------------------------------------------------|
| mgf-common      | **43 findings** (fixable). Mostly RUF100 unused-noqa (15) + N818 exception-name suffix (12). |
| mgf-alembic     | ✅ Clean.                                                                     |
| mgf-apiprobe    | ✅ Clean.                                                                     |
| mgf-django      | ✅ Clean.                                                                     |
| mgf-fastapi     | ✅ Clean.                                                                     |
| mgf-http        | ✅ Clean.                                                                     |
| mgf-sqlalchemy  | ✅ Clean.                                                                     |

### §3.1 mgf-common ruff backlog (43 findings)

| Code      | Count | Severity   | Action                                                                                                 |
|-----------|------:|------------|--------------------------------------------------------------------------------------------------------|
| RUF100    |   15  | Nit        | Auto-removable noqa directives left over from ruff version bumps. `ruff check --fix`.                  |
| N818      |   12  | **Audit**  | Exception classes without `Error` suffix (`HttpBadRequest`, `ProcessTimeout`, …). Cannot auto-rename — would be a breaking-public-API change. Hold for v1.0 → rename in v1.x deliberately. |
| I001      |   11  | Nit        | Import-block sort. `ruff check --fix`.                                                                 |
| F401      |    9  | Nit        | Unused imports. `ruff check --fix`.                                                                    |
| TC003/002/001 |  6 | Nit        | Move stdlib imports into TYPE_CHECKING blocks. `ruff check --fix`.                                     |
| PTH101/PTH105 |  2 | Nit        | `os.chmod` → `Path.chmod`. Already fixed in Wave 1/3 new modules; remaining are in older code.         |
| BLE001    |   16  | Carry      | "Do not catch blind Exception" — these are intentional last-resort handlers (crash sink, plugin loader). All have justified `noqa` already. RUF100 just shadows them. |
| Others    |  ~10  | Nit        | RUF002/003, SIM, E702, etc. — minor style.                                                             |

**Gap → Q-2 (BLOCKER for v1.0):** The N818 exception-name renames. Twelve
public exception classes (`HttpBadRequest`, `HttpUnauthorized`, …,
`HttpServiceUnavailable`, `ProcessTimeout`, `ProcessNonZeroExit`,
`ProcessSignaled`, `ServiceNotReady`) do not follow PEP-8's "Error" suffix.

Two options:

  a) **Rename at v1.0** (e.g., `HttpBadRequest` → `HttpBadRequestError`) and
     ship aliases for one major (deprecated). This is "rip the bandaid"
     and bakes the convention in for v1.x onward.
  b) **Keep the names** and add a `noqa: N818` per class with a comment
     explaining the public-API preservation choice. v1.0 ships with these
     names locked in *forever*.

The maintainer should pick (a) or (b) before v1.0. Default recommendation: **(a)**.

**Gap → Q-3:** The other 31 lint findings are auto-fixable and should be
swept in a `chore: ruff backlog` commit before v1.0 (NOT blocking; just
hygiene).

---

## §4 PyPI publication state (federation)

| Package                | PyPI version  | Local version | Drift                |
|------------------------|---------------|---------------|----------------------|
| mgf-common             | 0.34.0        | 0.40.0        | **6 releases behind** |
| mgf-alembic            | 0.1.1         | 0.4.1         | **3 releases behind** |
| mgf-apiprobe           | 0.4.0         | 0.5.1         | **1 release behind**  |
| mgf-django             | **NOT ON PYPI** | 0.4.1       | **B-1 blocker**       |
| mgf-fastapi            | 0.3.1         | 0.6.1         | **3 releases behind** |
| mgf-http               | 0.3.0         | 0.4.2         | **1 release behind**  |
| mgf-sqlalchemy         | 0.1.1         | 0.4.1         | **3 releases behind** |
| mgf-test-supervisor    | **NOT ON PYPI** | 0.1.1       | **B-2 — new sibling** (extracted 2026-05-26) |
| mgf-website-template   | **NOT ON PYPI** | n/a         | (template — intentional) |

**Gap → Q-4 (BLOCKER for v1.0):** All siblings + mgf-common have unreleased
local versions. The maintainer's known constraint is the private-PyPI-server
setup (paused until ready). v1.0 cannot ship until either:

  a) The private PyPI server is up + tokens distributed, OR
  b) The public PyPI account rate-limit cools off and the queue is drained.

This is the **single biggest non-engineering blocker** for v1.0.

mgf-django has never been published anywhere (B-1 from `pre_release_check.md`).
It will be the first-time publish and is subject to PyPI's "Too many new
projects created" rate-limit (the same 24h cooldown that bit mgf-website-template).

mgf-test-supervisor (B-2) was extracted from `mgf-common/scripts/_mtest/` on
2026-05-26 as a separate sibling library. Until it lands on PyPI, every
adopter declares it via `mgf-test-supervisor @ git+ssh://...` + the hatch
`allow-direct-references = true` opt-in. **Consumer-side validation
(2026-05-26)**: mgf-hrb's migration agent independently confirmed Q-4 is the
blocker preventing siblings from dropping the git+ssh source — same finding
arriving from the consumer side via the FEEDBACK channel. Once Q-4 closes,
the cleanup commit per adopter is mechanical (drop the `@ git+ssh://...`
suffix + remove the `[tool.hatch.metadata]` block).

---

## §5 Cross-repo standards alignment

Standards docs have moved to `mgf-standard`; siblings no longer vendor a
local copy. `mgf-common` wheels the standards as package data. Verify by hand-spot:

| Repo            | mgf-standard pin current? | DOC-13/14/15 referenced? |
|-----------------|-----------------------------|--------------------------|
| mgf-common      | Y (canonical wheel source)  | Y                        |
| Siblings        | Need verification           | Need verification        |

**Gap → Q-5:** No script today validates "every sibling references the same
mgf-standard version as mgf-common." Recommend adding
`tools/verify_standards_sync.py` to mgf-common that checksums the wheeled
standards and complains if a sibling drifts. *Not blocking v1.0; nice-to-have
for v1.0.1.*

---

## §6 Gate sign-off matrix (maintainer fills in)

| Gate | Description                                                          | Status      | Verdict |
|------|----------------------------------------------------------------------|-------------|---------|
| QG-1 | Federation test sweep green                                          | ✅ 2885 pass | Sign?   |
| QG-2 | Federation ruff clean (allow N818 carry per Q-2 decision)            | ⚠ Q-2/Q-3   | Sign?   |
| QG-3 | `PUBLIC_API.md` exists in every repo                                 | ✅           | Sign?   |
| QG-4 | `PUBLIC_API.json` pin in mgf-common (siblings deferred)              | ✅ (Q-1)     | Sign?   |
| QG-5 | CHANGELOG.md current in every repo                                   | ✅           | Sign?   |
| QG-6 | FEEDBACK.md present in every repo (Phase A)                          | ✅           | Sign?   |
| QG-7 | `docs/claude/` (consumer onboarding) in every repo                   | ✅           | Sign?   |
| QG-8 | `docs/cutover/` (release-prep) in every repo                         | ✅           | Sign?   |
| QG-9 | `mgf-standard` standards wheeled into mgf-common; siblings updated   | ✅ (Q-5 follow-up) | Sign? |
| QG-10| import-linter contracts present + green                              | ✅           | Sign?   |
| QG-11| Stability tier promotions reviewed (E1 doc)                          | ⏳ Pending   | Sign?   |
| QG-12| PyPI publication caught up (Q-4)                                     | ❌ BLOCKED   | Sign?   |

**Three real blockers between today and v1.0:**

  1. **Q-2** — Pick (a) rename + alias or (b) lock + noqa for N818 exceptions.
  2. **Q-4** — Drain the PyPI backlog (private server OR rate-limit recovery).
  3. **Q-11 / E1** — Maintainer signs off the §3 promotion proposals in
     `v1_0_stability_audit.md`.

Everything else is hygiene that can land before v1.0 cut or carry forward.

---

## §7 What this sweep deliberately did NOT do

- Did not run mypy (consumer-facing type contracts come from PUBLIC_API.md;
  in-tree mypy is a developer convenience, not a v1.0 gate).
- Did not edit any source file.
- Did not bump any version.
- Did not auto-fix ruff findings.
- Did not test under any Python version other than the in-venv default
  (federation tested on the same interpreter as Wave 1/2/3 development).

Pre-v1.0 the maintainer should additionally run:

  - `tox -e py310,py311,py312,py313` per repo (multi-Python matrix).
  - `mypy src/` per repo (gate at zero errors on src/).
  - `twine check dist/*` per repo after build.

These are deferred because they expand the matrix beyond what one
audit session can cover responsibly.
