# Release waves plan — federation execution

> **Status:** working document. Authored 2026-05-18 after the
> 2026-05-17 [`pre_release_check.md`](pre_release_check.md) +
> [`pre_release_additions.md`](pre_release_additions.md) audit, the
> inthewords starter-Suite adoption sweep (PAPER-35..44), and the
> maintainer's two-part directive:
> (1) execute Waves 1–4 from `pre_release_additions.md` one by one,
> (2) standardise FEEDBACK across all siblings + encode an ongoing
> reminder mechanism for consumers.
> **Audience:** the maintainer + future Claude sessions executing
> this plan.
> **NON-GOAL:** cutting v1.0. The maintainer reviews after Wave 4
> before green-lighting the v1.0 release.

---

## §1 What's new since 2026-05-17

While I was preparing the feature-roadmap analysis, inthewords ran a
parallel adoption sweep. That work has landed:

| Paper | Where filed | Where closed | Status |
|---|---|---|---|
| PAPER-35 — Aggregated consumer cutover guide | mgf-common FEEDBACK.md | not yet — federation-level | OPEN (correct location) |
| PAPER-36 — mgf-http streaming + body cap | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-http `[Unreleased]` (commit `4722bb3`) | needs move + release |
| PAPER-37 — mgf-http SSRF-safe redirect-walk recipe | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-http `[Unreleased]` (commit `4722bb3`) | needs move + release |
| PAPER-38 — Federation-wide README pin-window staleness | mgf-common FEEDBACK.md | All 7 sibling READMEs (separate commits each) | OPEN (correct location — federation-wide) |
| PAPER-39 — mgf-apiprobe `Probe.depends_on` | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-apiprobe `[Unreleased]` (commit `519ed9b`) | needs move + release |
| PAPER-40 — mgf-apiprobe `BearerAuth` scheme kwarg | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-apiprobe `[Unreleased]` (commit `75187bc`) | needs move + release |
| PAPER-41 — mgf-apiprobe default-check applicability | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-apiprobe `[Unreleased]` (commit `75187bc`) | needs move + release |
| PAPER-42 — mgf-apiprobe `Probe.id` auto-derive | mgf-common FEEDBACK.md ⚠️ MISFILED | mgf-apiprobe `[Unreleased]` (commit `75187bc`) | needs move + release |
| PAPER-43 — `mgf-fed migrate` cross-version codemod | mgf-common FEEDBACK.md | not yet | OPEN (correct location) |
| PAPER-44 — `catch-up --apply` `.bak` cleanup | mgf-common FEEDBACK.md | not yet | OPEN (correct location) |

**Six papers (36, 37, 39, 40, 41, 42) are misfiled — sibling-specific
feedback that landed in mgf-common's FEEDBACK file.** The fix code
is already in the sibling's `[Unreleased]` — but the PAPER narrative
should live in the sibling's own FEEDBACK file, not mgf-common's.

**Zero of the seven federation siblings has a `FEEDBACK.md` today.**
That's the structural gap that allowed the misfiling.

---

## §2 What the maintainer asked for

Four things, in order of foundational importance:

1. **Standardise FEEDBACK across the federation.** Every sibling
   MUST have a `FEEDBACK.md`. The misfiled papers above must move
   to the right home. The structure must be encoded in the
   DOCUMENTATION standard (`mgf-fed standards DOCUMENTATION`)
   as a permanent rule so future siblings don't repeat the gap.

2. **Standardise the two consumer-side trackers.** Every project
   that **adopts** mgf-common (consumer applications + federation
   siblings) MUST maintain:

   - **`MGF_ADOPTION.md`** — a living adoption tracker for
     mgf-common itself. Models:
     [inthewords/docs/MGF_COMMON_ADOPTION.md](https://codeberg.org/.../inthewords/.../docs/MGF_COMMON_ADOPTION.md)
     +
     [PlasmaMapper/docs/inprogress/MGF_ADOPTION.md](https://codeberg.org/.../PlasmaMapper/.../docs/inprogress/MGF_ADOPTION.md).
     Tracks pin-bump history, feature-adoption status, FEEDBACK
     paper closures, phase rollout.
   - **`MGF_STANDARDS_CONFORMANCE.md`** — a living conformance
     tracker against the engineering standards (`mgf-fed standards`).
     Model:
     [PlasmaMapper/docs/inprogress/MGF_STANDARDS_CONFORMANCE.md](https://codeberg.org/.../PlasmaMapper/.../docs/inprogress/MGF_STANDARDS_CONFORMANCE.md).
     Per-rule status table (✅ / 🚫 declined-with-rationale / ⏳
     / N/A). Conformance-level (L1 / L2 / L3) declared in README.

   Both shapes already exist in real consumers — the new rule
   codifies them. The shapes get templates + a standards section.

3. **Encode an ongoing-discipline reminder mechanism** so
   consumer projects continue filing PAPERs AND updating the
   two trackers without the maintainer reminding each session.
   The mechanism lives in `mgf-fed catch-up`'s auto-block
   (which already manages content in each consumer's
   `docs/CLAUDE.md`) AND in new standards rules.

4. **Then execute Waves 1–4** from
   [`pre_release_additions.md`](pre_release_additions.md):
   - Wave 1: mgf-common 0.35.0 + 0.36.0 (4 primitives).
   - Wave 2: sibling-side consumption + new primitives.
   - Wave 3: second-tier mgf-common primitives.
   - Wave 4: stability sweep (NOT a v1.0 cut).

5. **Stop after Wave 4.** Maintainer-side review before v1.0.

---

## §3 The plan — five phases, sequenced

```
Phase A — FEEDBACK + ADOPTION + CONFORMANCE standardisation
          (foundational; do first)
    ├── A1: Move misfiled papers
    ├── A2: Create FEEDBACK.md in every sibling
    ├── A3: Templates for the three tracker shapes
    ├── A4: Standards bump v2.8
    │       ├── DOC-13 + FB-01..04 (FEEDBACK discipline)
    │       ├── DOC-14 + ADP-01..04 (adoption-tracker rules)
    │       └── DOC-15 + CFM-01..04 (conformance-tracker rules)
    ├── A5: Each sibling gets its own
    │       MGF_STANDARDS_CONFORMANCE.md (siblings ARE adopters)
    ├── A6: Ongoing-discipline auto-block in catch-up
    │       ├── feedback-discipline section
    │       ├── adoption-discipline section
    │       └── conformance-discipline section
    └── A7: Commit + push

Phase B — Wave 1: mgf-common primitives (0.35.0 + 0.36.0)
    ├── B1: C-1 feature flags
    ├── B2: C-NEW-1 scheduler protocol
    ├── B3: release 0.35.0 (bundle: A3 standards + B1 + B2)
    ├── B4: C-NEW-2 plugin auto-discovery (PAPER-10)
    ├── B5: C-NEW-3 doctor-bundle primitive
    └── B6: release 0.36.0

Phase C — Wave 2: sibling consumption (six paired releases)
    ├── C1: mgf-http 0.4.0 (closes PAPER-36/37 + H-NEW-1 resumable download)
    ├── C2: mgf-sqlalchemy 0.4.0 (S-1 audit-trail + S-3 UUIDv7)
    ├── C3: mgf-apiprobe 0.5.0 (closes PAPER-39/40/41/42 + P-1 security checks)
    ├── C4: mgf-fastapi 0.6.0 (F-1 rate-limit + F-NEW-1 arq integration)
    ├── C5: mgf-django 0.4.0 (D-1 throttle + D-NEW-1 Celery integration)
    └── C6: mgf-alembic 0.4.0 (A-1 drift detector)

Phase D — Wave 3: second-tier mgf-common primitives
    ├── D1: C-2 rate-limit primitive
    ├── D2: C-3 idempotency-key store
    ├── D3: C-4 health-check primitive
    └── D4: C-5 cache abstraction

Phase E — Wave 4: stability sweep + HAND-OFF (NO v1.0 cut)
    ├── E1: AP-09 stability audit per package
    ├── E2: Federation-wide quality-gate sweep (per federation_roadmap §gates)
    ├── E3: Update pre_release_check.md state
    └── E4: HAND OFF TO MAINTAINER for v1.0 review
```

Phases run sequentially. Within a phase, items run sequentially
unless explicitly marked parallel-safe.

---

## §4 Phase A — FEEDBACK + ADOPTION + CONFORMANCE standardisation (the foundation)

This phase blocks Wave 2 sibling releases (because each sibling's
v0.x.y release commit should include its own `FEEDBACK.md`
**and** its own `MGF_STANDARDS_CONFORMANCE.md`). **Estimated
effort: one full session — was 1, expanded to 1 with the new
trackers.**

### A1 — Move misfiled papers (mgf-common → sibling)

For each of PAPER-36, 37, 39, 40, 41, 42:

1. Copy the paper's full entry from `mgf-common/FEEDBACK.md` into
   the appropriate sibling's new `FEEDBACK.md` under `§2 Open
   feedback (active)` (preserving the original filer attribution
   and the close-link to the sibling's commit).
2. Replace the mgf-common entry with a short redirect stub:
   > **MOVED to `mgf-<sibling>` repo.** This paper was originally
   > filed against mgf-common but is sibling-specific. Tracking
   > moved 2026-05-18; see
   > [`mgf-<sibling>/FEEDBACK.md`](https://codeberg.org/.../FEEDBACK.md#paper-NN).
3. Renumber within the sibling: papers in each sibling's
   FEEDBACK start at `PAPER-01` locally (the federation-wide
   number stays as a cross-reference in the title).

**Why this shape:** maintains traceability from the original
filer's session, preserves the GitHub-style "moved to other repo"
link, and lets each sibling have its own clean paper sequence.

### A2 — Create FEEDBACK.md in every sibling

Seven `FEEDBACK.md` files, one per sibling, all using the same
template (derived from mgf-common's existing structure):

```
# FEEDBACK — <sibling-name>

> Paper-tracking file for issues, friction, and requests
> against this sibling. Consumer projects (PlasmaMapper,
> inthewords, vm-vmanager-app, iosRecovery, and any future adopter)
> file PAPER-NN entries here.
>
> **Where to file what:** issues that touch only this sibling's
> public surface land HERE. Federation-wide concerns (cross-
> sibling patterns, standards proposals) land in
> [mgf-common/FEEDBACK.md](https://codeberg.org/.../mgf_common/.../FEEDBACK.md).

## §1 Process
## §2 Open feedback (active)
## §3 Reviewer's meta-feedback
## §4 How consumers submit feedback
## §5 Cross-references
```

mgf-website-template gets a FEEDBACK.md too — it's the template
repo, so its FEEDBACK collects feedback about the TEMPLATE shape,
not about generated consumer sites.

### A3 — Templates for the three tracker shapes

Three template files land in `mgf-common/docs/recipes/`
(reusable by any consumer / sibling):

- **[`feedback-md-template.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/recipes/feedback-md-template.md) (→ mgf-standard)** — the canonical
  shape: process / open feedback (active) / reviewer's
  meta-feedback / how to submit / cross-references. Mirrors
  mgf-common's existing `FEEDBACK.md` minus mgf-common-specific
  content.
- **`docs/recipes/mgf-adoption-md-template.md`** — the
  adoption-tracker shape: at-a-glance / strategic context /
  status snapshot / phase status / pin-bump history /
  FEEDBACK rounds / four-gates result. Distilled from
  PlasmaMapper's `MGF_ADOPTION.md` + inthewords'
  `MGF_COMMON_ADOPTION.md` (the two reference shapes).
- **`docs/recipes/mgf-standards-conformance-md-template.md`** —
  the conformance-tracker shape: scope / audit method / counts
  table / headline / per-rule audit. Distilled from PlasmaMapper's
  `MGF_STANDARDS_CONFORMANCE.md`.

Each template ships with placeholder text + clear "REPLACE ME"
markers so adopters fork-and-fill rather than start from
scratch.

### A4 — Standards bump v2.8

Three new bundles of rules in
[`DOCUMENTATION.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/DOCUMENTATION.md):

**Bundle 1 — FEEDBACK discipline:**

- **DOC-01 amendment** — add `FEEDBACK.md` to the "universal
  four" → "universal five." Cornerstone + federation siblings
  + consumer applications all MUST ship one.

  Carve-out: consumer applications MAY redirect their FEEDBACK
  to an upstream library if their feedback is exclusively
  against the upstream — but the file MUST exist with at least
  a pointer.

- **DOC-13** — "FEEDBACK files MUST be repo-scoped."
  Sibling-specific issues live in the sibling's own
  `FEEDBACK.md`. Federation-wide issues live in
  `mgf-common/FEEDBACK.md`. Cross-references encouraged.

- **FB-01** — paper numbering is local (`PAPER-NN` resets per
  repo); the federation-wide number lives in the entry title
  as a cross-reference.
- **FB-02** — every paper has a status row (`OPEN` / `SHIPPED`
  / `DEFERRED` / `WONTFIX` / `MOVED`) and a filer-attribution
  row.
- **FB-03** — papers SHIPPED carry a commit-SHA reference +
  release-version reference.
- **FB-04** — consumer-side discipline: file feedback at the
  sibling whose surface you're commenting on (the misfile
  that prompted this rule).

**Bundle 2 — ADOPTION-tracker discipline:**

- **DOC-14** — "Every project that depends on mgf-common (or
  any federation sibling) MUST maintain an `MGF_ADOPTION.md`
  tracker."
- **ADP-01** — Location: `docs/inprogress/MGF_ADOPTION.md`
  (recommended) OR `docs/MGF_ADOPTION.md` (alternate).
  README MUST link to it.
- **ADP-02** — Sections REQUIRED: §1 at-a-glance (pin / extras
  declared / status), §2 strategic context, §3 phase status,
  §4 pin-bump history, §5 FEEDBACK rounds (cross-references
  to the project's own FEEDBACK.md or to upstream FEEDBACKs).
- **ADP-03** — Update cadence: on every pin bump AND on every
  closed FEEDBACK paper that this project depends on.
- **ADP-04** — Federation siblings keep an adoption tracker
  too — they "adopt" mgf-common via the pin window, the
  catch-up auto-block, etc.

**Bundle 3 — CONFORMANCE-tracker discipline:**

- **DOC-15** — "Every project that adopts mgf-common's
  standards MUST maintain an `MGF_STANDARDS_CONFORMANCE.md`
  tracker."
- **CFM-01** — Location: `docs/inprogress/MGF_STANDARDS_CONFORMANCE.md`
  (recommended).
- **CFM-02** — Declared conformance LEVEL: L1 (minimal —
  universal-five + EH-* + DP-* core), L2 (observability-native
  — adds LG-* + OP-* + SC-*), L3 (full — every standard at
  full strength). Each project declares its level in README.
- **CFM-03** — Per-rule audit shape: each standard's rules
  (e.g., DP-01..DP-13, LG-01..LG-17, etc.) get a status
  marker: ✅ conformant / 🚫 declined-with-rationale / ⏳
  in-progress / N/A (rule doesn't apply to project shape).
- **CFM-04** — Documented non-adoption: a 🚫 status MUST
  carry a rationale per
  [`mgf-standard: non-adoption-is-valid.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/principles/non-adoption-is-valid.md)
  (ASPIRE-04 was the precedent).

This is a v2.8 standards bump. Bumps
[`mgf-standard/docs/standards/README.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/README.md)
"Versioning" section + adds a `V2_8_NOTIFICATION.md` broadcast
note in `docs/inprogress/` (same shape as the v2.6 / v2.7
notifications already there).

### A5 — Each sibling gets its own MGF_STANDARDS_CONFORMANCE.md

Federation siblings ARE adopters of mgf-common's standards.
Their conformance tracker lives at
`docs/inprogress/MGF_STANDARDS_CONFORMANCE.md` per ADP-04 /
CFM-01.

Each sibling's initial conformance audit is short — they're
small, focused surfaces. Most will declare L2 conformance
(observability-native) with a handful of N/A markers
(framework-specific carve-outs).

Initial audit per sibling produces ~7 sections (one per
standards group: DP, EH, LG, SC, AP, CF, TS) with mostly ✅ +
a few 🚫 declined-with-rationale entries inherited from the
v2.6 web-shape carve-outs.

(Federation siblings do NOT need an `MGF_ADOPTION.md` of their
own — their adoption relationship to mgf-common is documented
in the federation_roadmap + their own CHANGELOG. ADP-04
clarifies this carve-out.)

### A6 — Ongoing-discipline auto-block in `mgf-fed catch-up`

The codemod already manages BEGIN/END markers in each
consumer's `docs/CLAUDE.md`. Add THREE new auto-block sections
(one per discipline so they can evolve independently):

```
<!-- BEGIN mgf-common: feedback-discipline -->
When you encounter friction with mgf-common OR any federation
sibling, FILE A PAPER-NN ENTRY in the target's FEEDBACK.md
(per DOC-13). Sibling-specific = sibling's FEEDBACK.md;
federation-wide = mgf-common/FEEDBACK.md.

Required fields: title, filer (consumer name + date), problem
statement, reproducer / evidence, proposed shape, status
(OPEN). Don't wait for permission — the maintainer triages.
<!-- END mgf-common: feedback-discipline -->


<!-- BEGIN mgf-common: adoption-discipline -->
This project tracks its mgf-common adoption in
`docs/inprogress/MGF_ADOPTION.md` (per DOC-14 / ADP-01).
Update the tracker on EVERY pin bump (mgf-common or any
sibling) and on every FEEDBACK paper close that touches this
project. Format reference:
mgf-common/docs/recipes/mgf-adoption-md-template.md.
<!-- END mgf-common: adoption-discipline -->


<!-- BEGIN mgf-common: conformance-discipline -->
This project's standards conformance is tracked in
`docs/inprogress/MGF_STANDARDS_CONFORMANCE.md` (per DOC-15 /
CFM-01). Declared conformance level: see README.

When a standard's rule changes (mgf-common standards bump),
or when this project changes code that touches a standards
rule, update the per-rule status (✅ / 🚫 declined / ⏳ /
N/A). Decline-with-rationale per CFM-04.

Format reference:
mgf-common/docs/recipes/mgf-standards-conformance-md-template.md.
<!-- END mgf-common: conformance-discipline -->
```

Implementation:
- Extend `mgf.common.codemod._auto_block.STANDARD_BLOCKS` (or
  equivalent) with the three new BEGIN/END markers.
- New unit test in `tests/unit/codemod/test_auto_block.py`
  pinning the three blocks render correctly into a fresh
  consumer skeleton + idempotently in subsequent runs.
- `mgf-fed catch-up --apply` against each known consumer
  (vm-vmanager-app, PlasmaMapper, inthewords, iosRecovery) pushes the
  new blocks. (CONSUMERS get this update on their NEXT
  catch-up; we don't push into their repos from this side.)

### A7 — Commit + push

Single commit per repo where the work touched (mgf-common gets
multiple commits — one per logical group; each sibling gets one
commit for FEEDBACK.md + MGF_STANDARDS_CONFORMANCE.md).
Commits go via standard `git push origin main` with the
Codeberg SSH-key flag.

**Phase A exit criteria:**
- 6 papers moved (mgf-common FEEDBACK redirect-stubs + sibling
  FEEDBACK entries).
- 7 sibling `FEEDBACK.md` files created.
- 7 sibling `MGF_STANDARDS_CONFORMANCE.md` files created
  (initial L2 audit).
- 3 templates landed in `mgf-common/docs/recipes/`.
- DOC-01 amended + DOC-13/14/15 + FB-01..04 + ADP-01..04 +
  CFM-01..04 in standards.
- `V2_8_NOTIFICATION.md` in `docs/inprogress/`.
- `catch-up` auto-block extended with three new BEGIN/END
  sections + unit test pins them.
- All commits pushed to Codeberg.

---

## §5 Phase B — Wave 1: mgf-common primitives

Two releases: `0.35.0` and `0.36.0`. Each release groups two
related primitives. Each goes through the same flow as the
2026-05-17 `0.34.0` ship (REL-06 ordering: bump → regenerate
PUBLIC_API.json → build → test → twine check → commit → tag →
push tag → upload).

### B1 — C-1 feature flags

Public surface (target):
```python
# mgf.common.flags

@runtime_checkable
class FeatureFlag(Protocol):
    def is_enabled(self, name: str, *, default: bool = False,
                   context: Mapping[str, Any] | None = None) -> bool: ...

class EnvVarFlags(FeatureFlag):
    """Env-var-backed; reads MGF_FLAG_<NAME>=1/0 at call-time.
    Default implementation; stdlib-only."""

class StaticFlags(FeatureFlag):
    """In-process dict; for tests."""

def configure_flags(impl: FeatureFlag) -> None: ...
def is_enabled(name: str, *, default: bool = False, ...) -> bool: ...
```

Behaviour:
- Module-level `is_enabled(...)` reads from the configured impl
  (default `EnvVarFlags`).
- On flip: structured INFO emission with `event="mgf.flag_flipped"`
  + `audit=True` per LG-04 (audit log standard).
- Stable tier: `experimental` at 0.35.0; promote at v1.0.

Tests: ~25 unit tests covering protocol, EnvVarFlags + StaticFlags,
audit-emission, context-aware overrides, thread safety.

### B2 — C-NEW-1 scheduler protocol

Public surface (target):
```python
# mgf.common.schedule

@runtime_checkable
class Scheduler(Protocol):
    def schedule(self, expr: str, *, fn: Callable[[], None],
                 name: str | None = None) -> ScheduledTask: ...
    def tick(self, *, now: datetime | None = None) -> list[ScheduledTask]: ...

class CronExpression:
    """Stdlib-only cron-expression parser. Supports the standard
    5-field shape + the @hourly / @daily / @weekly / @monthly aliases."""

    @classmethod
    def parse(cls, expr: str) -> CronExpression: ...
    def next_fire(self, *, after: datetime) -> datetime: ...
    def matches(self, ts: datetime) -> bool: ...

class InProcessScheduler(Scheduler):
    """Tick-driven; consumer drives `.tick()` from its event loop /
    timer / whatever scheduling shell already exists."""
```

Why this shape:
- Protocol-only — backends (arq, Celery, systemd, cron) wire
  externally.
- `CronExpression` ships as a standalone parser — useful even if
  the `Scheduler` protocol isn't adopted (vm-vmanager-app + iosRecovery
  could use just the parser).
- Tick-driven default avoids importing a thread / timer at module
  load.

Tests: ~30 unit tests; cron-expression parser exhaustively tested
(every alias + edge cases); InProcessScheduler tick semantics.

### B3 — Release mgf-common 0.35.0

Bundle: A3 standards-v2.8 + B1 + B2.

CHANGELOG entries:
- Standards v2.8 (FEEDBACK universal-five + DOC-13 + FB-01..04)
- New `mgf.common.flags` (4 names; experimental)
- New `mgf.common.schedule` (4 names; experimental)

PUBLIC_API surface grows by 8 names. Stability tier
`experimental` per AP-11.

Release flow: REL-06 ordering, same as 0.34.0.

### B4 — C-NEW-2 plugin auto-discovery (PAPER-10)

Public surface (target):
```python
# mgf.common.plugins

@runtime_checkable
class PluginGroupRegistrar(Protocol):
    def discover(self, group: str) -> list[PluginRecord]: ...

class PluginRecord:
    name: str
    obj: Any
    distribution: str
    version: str

def discover(group: str, *, required: type[T] | None = None) -> list[PluginRecord]:
    """Iterate `importlib.metadata.entry_points(group=group)`.
    Filter by `required` Protocol if given (skip + warn on
    non-conformant entries — closed-box discipline).
    Audit-log every discovery + every load attempt."""
```

Closes PAPER-10 (originally DEFERRED until 2nd-consumer
evidence). Promoted now because PlasmaMapper's TelematicsProvider
is the live evidence (Teltonika first; Queclink + Ruptela
queued).

Tests: ~15 unit tests using a fake entry-point group; covers
discovery, filtering, audit emission, error handling.

### B5 — C-NEW-3 doctor-bundle primitive

Public surface (target):
```python
# mgf.common.doctor

@dataclass(frozen=True)
class DoctorReport:
    app_name: str
    app_version: str
    when: datetime
    sections: tuple[ReportSection, ...]

@dataclass(frozen=True)
class ReportSection:
    name: str
    status: Literal["ok", "warn", "fail"]
    details: Mapping[str, Any]   # redacted at construction

class DoctorBundle:
    """Composes a redacted diagnostic bundle: text report + JSON.
    Subclassable; ships built-in sections for settings, version,
    paths, runtime."""

    def render_text(self) -> str: ...
    def render_json(self) -> dict[str, Any]: ...
    def write_to(self, path: Path) -> None: ...  # 0o600
```

Generalises the existing `mgf-fed app-doctor` CLI command's
report-rendering logic into a reusable primitive. vm-vmanager-app's
existing "doctor bundle" pattern + iosRecovery's planned
`figrecovery doctor bundle` both wire this.

Tests: ~20 unit tests; redaction discipline verified; file mode
verified.

### B6 — Release mgf-common 0.36.0

Bundle: B4 + B5.

PUBLIC_API surface grows by ~7 names.

---

## §6 Phase C — Wave 2: sibling consumption (six releases)

Each sibling release goes through the full flow: bump version
+ pin → CHANGELOG drain → tests → ruff → mypy → commit → tag →
push to Codeberg → build → twine check. **PyPI upload is gated
on the private-index availability** — at the time of writing,
the maintainer is standing up a private PyPI; until that's
ready, releases stop after Codeberg push + local `dist/` build.

The six releases below run sequentially in this order (dependency
order — sibling X release goes BEFORE sibling Y if Y depends on
X). Ship one, verify, move to next.

### C1 — mgf-http 0.4.0
Bundles:
- PAPER-36 (max_response_size + .stream()) — already in `[Unreleased]`
- PAPER-37 (SSRF-safe redirect-walk recipe) — already in `[Unreleased]`
- **H-NEW-1 resumable + SHA-verified download** — NEW (iosRecovery + vm-vmanager-app evidence)

Pin: `mgf-common>=0.34,<0.35` → `>=0.36,<0.37` (catches Wave 1).

### C2 — mgf-sqlalchemy 0.4.0
Bundles:
- **S-1 audit-trail mixin** (created_at/updated_at/deleted_at/created_by_id/updated_by_id)
- **S-3 UUID v7 primary-key helper**

Pin: `mgf-common>=0.33,<0.34` → `>=0.36,<0.37`.

### C3 — mgf-apiprobe 0.5.0
Bundles:
- PAPER-39 (Probe.depends_on) — already in `[Unreleased]`
- PAPER-40 (BearerAuth scheme kwarg) — already in `[Unreleased]`
- PAPER-41 (default-check applicability) — already in `[Unreleased]`
- PAPER-42 (Probe.id auto-derive) — already in `[Unreleased]`
- **P-1 missing-security-header checks** (CSP / Referrer-Policy / Permissions-Policy) — closes deferred SH-05

Pin: `mgf-common>=0.34,<0.35` → `>=0.36,<0.37`.

### C4 — mgf-fastapi 0.6.0
Bundles:
- **F-1 rate-limit middleware** (wires C-2 → but C-2 ships in Wave 3; for this release, F-1 wires the lower-level mgf-common.flags + mgf-common.schedule OR ships its own bucket pending C-2)
- **F-NEW-1 arq integration** (lifespan + BackgroundTaskProtocol impl backed by arq)

Pin: `mgf-common>=0.33,<0.34` → `>=0.36,<0.37`.
Sibling pin: `mgf-sqlalchemy>=0.1,<0.2` → `>=0.4,<0.5` (catches C2).

**Decision needed before C4:** does F-1 wire C-2 (Wave 3's
formal protocol) or ship its own bucket? Recommendation: ship
its own minimal bucket at C4, re-base on C-2 in Wave 3 when
C-2 ships. F-1 stays `experimental`, so the rebase is allowed.

### C5 — mgf-django 0.4.0
Bundles:
- **D-1 brute-force throttle** (login-shape; wires mgf-common.flags + an internal bucket pending C-2)
- **D-NEW-1 Celery integration helpers** (bootstrap ↔ Celery worker lifecycle; periodic tasks via C-NEW-1 scheduler protocol)

Pin: `mgf-common>=0.33,<0.34` → `>=0.36,<0.37`.

### C6 — mgf-alembic 0.4.0
Bundles:
- **A-1 migration drift detector** (CI-friendly: diff `Base.metadata` against the DB; warn on unrepresented changes)

Pin: `mgf-common>=0.34,<0.35` → `>=0.36,<0.37`.

NOTE: this is on top of the already-tagged mgf-alembic v0.3.0
(committed `f3d3473`, built locally, awaiting PyPI token). When
the private PyPI lands, v0.3.0 ships FIRST (its dist/ is
already built); v0.4.0 follows. If the private PyPI is up
before Phase C starts, just collapse v0.3.0 + v0.4.0 into one
0.4.0 release including everything.

---

## §7 Phase D — Wave 3: second-tier mgf-common primitives

| # | Primitive | Why this comes AFTER Wave 2 |
|---|---|---|
| **D1** | C-2 rate-limit primitive (`mgf.common.rate_limit.TokenBucket` / `LeakyBucket`) | Wave 2 siblings (F-1 + D-1) already ship rate-limit functionality. C-2 formalises the protocol; siblings re-base on it in their NEXT minor. |
| **D2** | C-3 idempotency-key store (`IdempotencyStore` protocol + in-memory impl) | Pairs with mgf-http's PAPER-NN (idempotency-key on POST) — Wave 4 candidate. |
| **D3** | C-4 health-check primitive (`HealthCheck` enum + component check protocol) | Aligns with **OP-04**; mgf-fastapi adds route helpers in v0.7. |
| **D4** | C-5 cache abstraction (`Cache` protocol + LRUCache + NullCache) | Most-deferred Wave-1 candidate; ships in Wave 3 once we have evidence about who actually wires backends. |

Each D-item is a single mgf-common MINOR release. Could bundle
D1 + D2 in one release, D3 + D4 in another. Decide at the
moment based on velocity.

---

## §8 Phase E — Wave 4: stability sweep + HAND-OFF

**No code changes.** Audit + report.

### E1 — AP-09 stability promotion audit

For each package (mgf-common + 7 siblings):

1. List every public name in `PUBLIC_API.md`.
2. Tag each with: `experimental` (post-Wave-2 additions), `stable`
   (pre-2026-05-17 names), or `deprecated` (none expected).
3. For each `experimental`, decide: promote to `stable` at v1.0?
   Or hold one more MINOR?
4. Surface the decision matrix in
   `docs/inprogress/v1_0_stability_audit.md`.

This is the [`federation_roadmap.md`](federation_roadmap.md)
§v1.0 "promote experimental → stable" pass.

### E2 — Federation-wide quality-gate sweep

Walk [`federation_roadmap.md`](federation_roadmap.md) §Quality
gates and verify each gate for each sibling:

- Tests pass (pytest in mgf-common AND each sibling): 100% green.
- mypy --strict on `src/`: zero errors.
- ruff check: zero errors.
- Coverage ≥ 85%.
- PUBLIC_API.md / .json pin tests pass.
- CLAUDE.md auto-block present + clean.
- v0.x cutover guide present (each sibling).
- Inter-package coupling (import-linter): zero leaks.
- PyPI verification (smoke `pip install` test): passes.
- Consumer notification (REL-09): drafted.

Output: federation-wide sign-off matrix in
`docs/inprogress/v1_0_quality_gates.md`.

### E3 — Refresh existing release-prep docs

- Update [`pre_release_check.md`](pre_release_check.md) §3 to
  reflect what's resolved (much of the original B-3 / B-4 / B-5
  block is now done via Phases C / Phase A).
- Update [`pre_release_additions.md`](pre_release_additions.md)
  §11 retrospective log.

### E4 — HAND OFF

This phase ENDS with a brief summary commit + a pointer to all
three docs (pre_release_check, pre_release_additions, this
plan) + the new v1.0 audits. Maintainer reviews offline. v1.0
cut waits for explicit green-light.

---

## §9 What I'll do at the start of each phase

For each phase, I'll:

1. State which phase I'm starting + reference this doc + the
   relevant section.
2. Create TaskCreate entries for the items in that phase so
   progress is visible.
3. Execute item-by-item; commit at each completed item; push
   to Codeberg.
4. At phase end, update this doc's `§11 Retrospective log`.

## §10 What WON'T happen

These are explicitly out-of-scope for this engagement:

- **v1.0 cut.** Stops at Phase E hand-off.
- **PyPI uploads for token-blocked siblings.** Built dist/ stays
  local; private-index landing later.
- **New consumer projects.** Doesn't touch vm-vmanager-app, inthewords,
  PlasmaMapper, or iosRecovery code paths — only the
  `mgf-fed catch-up`-managed auto-block in their
  `docs/CLAUDE.md`.
- **Email / file-storage / SSO adapters.** Demoted per
  consumer-evidence — wait for 2-consumer signal.
- **`mgf-meta` package, mgf-flask, mgf-django-drf siblings.**
  Federation roadmap §"Future improvements" — post-v1.0 only.

---

## §11 Retrospective log

| Date | Event |
|---|---|
| 2026-05-18 | Plan authored. Reflects pre_release_check.md + pre_release_additions.md + 2026-05-17 inthewords adoption-sweep papers (PAPER-35..44, 6 misfiled). Awaiting maintainer go-ahead before executing Phase A. |
| 2026-05-18 (later) | Plan EXPANDED at maintainer's request to add the two consumer-side trackers (`MGF_ADOPTION.md` + `MGF_STANDARDS_CONFORMANCE.md`) to the v2.8 standards bump. Phase A grew from 4 sub-steps to 7. New rule bundles: DOC-14 + ADP-01..04 (adoption) and DOC-15 + CFM-01..04 (conformance). Three templates land in `docs/recipes/`. `catch-up` auto-block grows from 1 BEGIN/END section to 3. Effort estimate unchanged — adoption + conformance are mechanical applications of patterns inthewords + PlasmaMapper already shipped, just newly codified. |
