# mgf-common v0.32.0 — `catch-up` understands pip-tools projects

> **Audience:** consumers running `mgf-fed catch-up` on projects
> that declare deps via the pip-tools layout (`requirements/*.{txt,lock}`)
> rather than PEP 621 `pyproject.toml [project] dependencies`.

This is a **stabilization-window release**: the federation roadmap
closes new public-surface additions in mgf-common after v0.31, but
behaviour-level improvements to existing tooling are in scope. PAPER-15
is the first such item — extending `mgf-fed catch-up` to audit
pip-tools projects as first-class manifests.

There is **no migration step** for pyproject-based projects. If your
project has a `pyproject.toml`, this release is a no-op for you.

---

## What changed

### Before (v0.17.2 → v0.31.0)

A project shaped like inthewords —

```
inthewords/
├── manage.py
├── requirements/
│   ├── base.txt          (runtime deps, includes `mgf-common>=…,<…`)
│   ├── base.lock
│   ├── dev.txt
│   ├── dev.lock
│   ├── prod.txt
│   └── prod.lock
├── pytest.ini
├── mypy.ini
├── ruff.toml
└── .coveragerc
```

— when audited, produced a single info-level row that told the
consumer: "your project uses pip-tools, full audit is deferred,
workaround is to add a minimal `pyproject.toml`". Two of the six
audit rows (mgf-common pin + four-gate config) couldn't actually be
audited.

### After (v0.32.0)

The same project gets full audit coverage:

| Audit row | Source |
|---|---|
| `requirements/* — mgf-common pin` | reads from `requirements/base.txt` (fallbacks: `main.txt`, `runtime.txt`, root `requirements.txt`) |
| `requirements/* — four gates` | reads from `pytest.ini` / `ruff.toml` / `mypy.ini` / `.coveragerc` (with `setup.cfg [tool:pytest]` + `setup.cfg [mypy]` + `tox.ini [pytest]` recognised as alternatives) |

Staleness detection, auto-rewrite (`--apply`), and the editable-install
guard from [PAPER-20](../../FEEDBACK.md) all apply uniformly across
pyproject-based and pip-tools-based projects.

---

## Recognised files

### Pin location (first match wins)

```
requirements/base.txt        ← canonical pip-tools runtime manifest
requirements/main.txt        ← alternative naming
requirements/runtime.txt     ← another alternative
requirements.txt             ← flat single-file layout (root)
```

Lock files (`*.lock`) are pip-compile output, not authoritative for
the human-readable pin — the audit reads `.txt` files.

The expected line shape in the manifest:

```
mgf-common>=0.31,<0.32
```

Extras are supported: `mgf-common[fastapi]>=0.31,<0.32`. Inline
comments after the constraint are preserved across `--apply` rewrites.

### Four-gate config files

| Gate | Recognised locations (in probe order) |
|---|---|
| **ruff** | `ruff.toml`, `.ruff.toml` |
| **mypy** (with `strict = True`) | `mypy.ini`, `.mypy.ini`, `setup.cfg [mypy]` |
| **pytest** (with `filterwarnings = error`) | `pytest.ini`, `setup.cfg [tool:pytest]`, `tox.ini [pytest]` |
| **coverage** | `.coveragerc`, `coverage.ini` |

Multi-line `filterwarnings` is accepted (a line containing `error`
satisfies the gate, mirroring pytest's own matcher).

---

## Example: re-run `catch-up` on an existing pip-tools project

```bash
$ mgf-common catch-up
mgf-fed catch-up — auditing /home/bassam/PycharmProjects/inthewords
  Project:        inthewords (kind: django)
  mgf-common:     0.32.0

  ✓ requirements/* — mgf-common pin    declared in `requirements/base.txt` …
  ⚠ requirements/* — four gates        missing or partial: .coveragerc (or coverage.ini); …
  ⚠ v0.1-pattern audit                 0 legacy call sites
  …
```

The "deferred follow-up" info row is gone; in its place is a real
audit you can act on.

---

## Auto-rewrite (`--apply`) for pip-tools projects

```bash
$ mgf-common catch-up --apply
…
  ⚠ requirements/* — mgf-common pin
    STALE: declared `>=0.16,<0.18` in `requirements/base.txt` but
    current mgf-common is `0.32.0` — the upper bound excludes it.
    Suggest bumping to `>=0.32.0,<0.34` (2-minor window).
    Run with --apply to rewrite the line; backup written.
    → applied: bumped pin to `>=0.32.0,<0.34` in
      requirements/base.txt
      (backup: base.txt.bak.1747000000)
```

Backups land alongside the original file (`base.txt.bak.<timestamp>`).
The rewrite is conservative — it targets exactly the matched substring
and preserves extras, inline comments, and the rest of the file.

If you're running an editable mgf-common (`pip install -e ../mgf_common`),
the auto-rewrite is REFUSED with a clear "verify against PyPI" message —
same guard as the pyproject path, per [PAPER-20](../../FEEDBACK.md).

---

## What about the lock files?

The audit does not touch lock files (`*.lock`). After `--apply`
rewrites `requirements/base.txt`, regenerate the lock as you normally
would:

```bash
pip-compile requirements/base.txt -o requirements/base.lock
```

This is the same workflow you'd use for any other pin change. The
audit just makes the "should the pin change?" decision visible.

---

## Federation context

This release opens the v0.32+ stabilization window. The roadmap calls
for no new mgf-common public surface in this window; PAPER-15's full
fix is an existing-behaviour fix to the catch-up CLI, not a new public
name, so it lands cleanly.

For consumers who need NEW surface (e.g. `bearer_session` from
PAPER-29), look to sibling minor releases — `mgf-fastapi v0.3.0` ships
that one. Each sibling's semver is independent of mgf-common's.

---

## Cross-references

- [`FEEDBACK.md` — PAPER-15](../../FEEDBACK.md) — the filing this release closes.
- [`FEEDBACK.md` — PAPER-20](../../FEEDBACK.md) — the editable-install guard PAPER-15 inherits.
- [`docs/release/federation_roadmap.md`](../release/federation_roadmap.md) — the v0.32+ stabilization-window definition.
