# Reliability & Accuracy

> **Status:** v0.2 — second pass. Last updated 2026-05-12.
> The first pass was a breadth audit; this pass walked the
> load-bearing modules end-to-end, verified every claim against
> `file:line`, dropped false positives, and added the systemic
> patterns the first pass missed (notably the atomic-write
> inconsistency across three sites and the docstring drift left
> over from v0.33.0).
>
> **Scope:** v1.0 readiness. Items beyond v1.0 are noted but
> deprioritised here; revisit when the v1.0 surface-lock review opens.
> **Audience:** Bassam-tomorrow, AI coding agents, and future hires
> doing reliability work on the federation.
> **Cross-references:** [`PUBLIC_API.md`](../../PUBLIC_API.md),
> engineering standards (`mgf-fed standards <TOPIC>`),
> [`FEEDBACK.md`](../../FEEDBACK.md) §2 (open papers — at the time of
> writing, the FEEDBACK backlog is essentially clean; this tracker is
> the next pass, focused on *internal* invariants rather than consumer
> papercuts).

This document is the **living priority tracker** for reliability +
accuracy work in `mgf-common`. The shape mirrors PlasmaMapper's
[`RELIABILITY_AND_ACCURACY.md`](../../../PlasmaMapper/docs/inprogress/RELIABILITY_AND_ACCURACY.md):
priority table at the top, work-unit detail below, status flipped as
items close.

The library is in a stabilization window heading into v1.0. Once the
public surface locks, regressions are expensive — both for us and for
every sibling/consumer downstream. This tracker exists so the
load-bearing invariants get the same attention the obvious feature
work has gotten.

---

## §1 You are here

The library passed 1318 tests, ships under `mypy --strict`, and the
v0.32 chapter promoted 111 names to stable. The AP-12 deprecation
cycle ran cleanly through v0.33.0. Surface-level quality is high.

What this tracker exposes is the **second-order** stuff — the
invariants that hold under the happy path but might not under stress,
contention, or partial failure. The library is meant to serve for
many years across multiple consumers and siblings; the cost of a
silent failure (a zombie process, a vault file lost on power loss, a
log handler that races and drops records) is paid years from now,
far from this codebase.

**Counts (last refreshed 2026-05-14, after the P0+P1 close-out):**

| Priority | Count | Effort | Status |
|---|---|---|---|
| P0 — v1.0 surface-lock blockers | 7 | ~2.5 session-weeks (1×L + 4×M + 2×S) | ✅ all closed (RA-01..RA-06 + RA-15) |
| P1 — should land before/with v1.0 | 11 | ~3 session-weeks (1×L + 4×M + 6×S) | ✅ all closed (RA-07..RA-14 + RA-16 / RA-17 / RA-18) |
| P2 — defer to post-v1.0 | 10 | — | 5 closed (RA-19 + RA-20 + RA-21 + RA-22 + RA-30); 5 explicitly deferred to v1.1+ (RA-23..RA-27 — all L/M-effort hardening work, not v1.0 blockers) |

**P0 + P1 close-out (2026-05-12 → 2026-05-14):** 18 items
landed across a single intensive session-week; every closure
carries a real commit SHA in §5. The library now holds the
"redact before any off-box egress" + "atomic-write everywhere"
+ "concurrent-bootstrap-safe" invariants the rest of the
roadmap leans on. Counts table will refresh again if/when
P2 items are pulled forward.

**Effort calibration:** S ≤ 1 day, M ≈ 2–4 days, L ≈ 1 session-week.
Recalibrated against the actual P0+P1 closure pace: the S/M items
landed at roughly the predicted rate; L items (RA-11 perf pins,
RA-14 cross-platform paths) ran slightly under the L budget.
Items are intentionally narrow — each one is a concrete commit,
not a research project.

### What changed between v0.1 (first pass) and v0.2 (second pass)

- **Sharpened:** every item now carries verified `file:line`
  evidence. Items that read fine in v0.1 but turned out to be
  imprecise were rewritten (e.g. RA-01 was "vault fsync"; it is
  actually a **systemic** atomic-write gap across three call sites,
  upgraded to RA-01 with an extracted helper).
- **Dropped (false positives):**
  - "Redactor extra_value_patterns mutability" — the field is a
    `tuple`; immutable by construction.
  - "Redactor lacks property-based tests" — they exist in
    [`test_redaction_property.py`](../../tests/unit/observability/test_redaction_property.py).
  - "No vulnerability scanning" — `pip-audit --strict` is wired in
    [`.woodpecker.yml`](../../.woodpecker.yml) line 204.
- **Added (second pass found):**
  - **RA-15** — `bootstrap()` replace semantics tear down the old
    context before the new one wires; if the new wiring fails, the
    process is left with NO context.
  - **RA-16** — `_unwire_otel` can't truly unwire (OTel
    `set_tracer_provider` is one-shot per process); document or fail loud.
  - **RA-17** — `_BootstrapLogBuffer.flush_to_stderr` has no formatter;
    operators see stripped records when bootstrap fails.
  - **RA-18** — Doc drift left over from v0.33.0 in
    `_identity.py` / `_warnings.py` (references to removed
    `configure` / `make_settings_config` / `EnvironmentError`).
  - **RA-19** — `bootstrap_for_test(capture_spans=True)` leaks span
    processors across tests.
  - **RA-20** — `JsonFormatter._RESERVED_RECORD_ATTRS` is a
    hardcoded allowlist; future Python versions adding new
    `LogRecord` attrs will pollute the JSON schema with internal
    fields.
  - **RA-21** — `AppContext.reload()` failure-with-restore leaves
    the caller's `ctx` reference stale (it was `shutdown()`'d before
    the restore swung into action); document the contract.
  - **RA-22** — `_maybe_emit_runtime_snapshot` builds the snapshot
    dict OUTSIDE a try/except. If `settings.model_dump` raises,
    the AppContext is already in `_GLOBAL_CONTEXT` but bootstrap()
    raises.

---

## §2 Priority table

### P0 — v1.0 surface-lock blockers (7 items)

| ID | Theme | One-liner | Effort | Status |
|---|---|---|---|---|
| [**RA-01**](#ra-01-systemic-atomic-write-helper) | Atomicity | Three atomic-write sites with three different patterns; only `versioned/_store.py` fsyncs. Vault + crash-reporter skip fsync entirely. Extract a shared helper. | M | ✅ closed |
| [**RA-02**](#ra-02-rollback-chain-failure-injection-test) | Bootstrap atomicity | No test proves the LIFO rollback completes when a rollback step ITSELF raises | M | ✅ closed |
| [**RA-03**](#ra-03-concurrent-bootstrap-on-logging-stack) | Concurrency | Parallel `bootstrap()` from two threads races on `logging.root.handlers` — `_RELOAD_LOCK` only held in `reload()`, not initial `bootstrap()` | M | ✅ closed |
| [**RA-04**](#ra-04-_yaml_file_override-classvar-concurrency) | Concurrency | `BaseAppSettings._yaml_file_override: ClassVar` cross-contaminates under concurrent `load_settings` | M | ✅ closed |
| [**RA-05**](#ra-05-dependency-upper-bounds) | Supply chain | `pydantic` / `pydantic-settings` / `pyyaml` declared floor-only; a breaking 3.0 propagates into every consumer | S | ✅ closed |
| [**RA-06**](#ra-06-process-reap-pin) | Resource hygiene | After `_terminate()` SIGKILLs a child, a second 2 s `proc.wait()` failure returns silently — no test, no log | M | ✅ closed |
| [**RA-15**](#ra-15-bootstrap-replace-semantics) | Lifecycle | `bootstrap()` calls `prior.shutdown()` BEFORE re-wiring; if re-wiring fails, the process is left context-less and the "bootstrap.replace" AUDIT log lands in a torn-down logging stack | S | ✅ closed |

### Suggested first wave

When implementation starts, do this batch first — four small,
mechanical, high-confidence items that pay back immediately and
prove the doc → code feedback loop:

1. **RA-05** (S) — add upper bounds on `pydantic` / `pydantic-settings` /
   `pyyaml`. Catches a future MAJOR-bump regression in CI before
   consumers do. Twenty-line `pyproject.toml` diff.
2. **RA-18** (S) — sweep doc drift left over from v0.33.0
   (`_identity.py`, `_warnings.py`, possibly more). Pure-comment
   changes; can land in a single PR.
3. **RA-08** (S) — add `fail_under = 85` to `[tool.coverage.report]`.
   The cookiecutter template already has this; the library itself
   doesn't.
4. **RA-15** (S) — guard `bootstrap()` replace semantics so a failed
   replace falls back to the prior context instead of leaving the
   process bare. One re-ordering of `prior.shutdown()` after the new
   wiring succeeds.

That batch closes 4 items in well under a session-week and unblocks
the M-items by establishing the discipline.

**Second wave** (M-effort P0): **RA-01** (the systemic atomic-write
helper) goes first because three downstream items use it. **RA-02**
(rollback chain failure-injection) lays the test harness that
**RA-03** (concurrent bootstrap lock) verifies. **RA-04** (`_yaml_file_override`
concurrency) is independent. **RA-06** (process-reap) needs
`psutil`; consider whether it joins `[dev]` extras or stays optional.

---

### P1 — should land before/with v1.0 (11 items)

| ID | Theme | One-liner | Effort | Status |
|---|---|---|---|---|
| [**RA-07**](#ra-07-streamer-thread-exception-visibility) | Observability | `_StreamCapture._pump` swallows exceptions from `readline()`; thread dies silently | S | ✅ closed |
| [**RA-08**](#ra-08-coverage-fail_under) | CI gates | `[tool.coverage.report] fail_under` not configured; coverage drift invisible | S | ✅ closed |
| [**RA-09**](#ra-09-process_group-on-windows-warning) | Cross-platform | `process_group=True` silently downgrades to per-PID `terminate()` on Windows; no warning | S | ✅ closed |
| [**RA-10**](#ra-10-public_apimd-vs-source-lint) | API discipline | `PUBLIC_API.md` drift vs `__all__` not caught by a lint rule (the JSON pin catches some but not all surfaces) | S | ✅ closed |
| [**RA-11**](#ra-11-perf-pins-beyond-lg-12) | Perf budgets | Only LG-12 (per-record logging) has a perf pin; `bootstrap()` / `Redactor.redact` / `JsonFormatter.format` / `current_context()` are untimed | M | ✅ closed |
| [**RA-12**](#ra-12-redactor-pattern-coverage-property-test) | Security | Per-pattern coverage property test: generate hundreds of valid samples of each named format, assert the redactor catches them | M | ✅ closed |
| [**RA-13**](#ra-13-appconfigerrorkindmigrate_failed-unused) | Diagnostics | `AppConfigErrorKind.MIGRATE_FAILED` defined but never raised; consumer `match e.kind` patterns can't catch migration failure | S | ✅ closed |
| [**RA-14**](#ra-14-cross-platform-config-paths-test-windows) | Cross-platform | `default_log_path()` / `default_config_path()` Windows branches lack a unit test that monkeypatches `sys.platform = "win32"` | M | ✅ closed |
| [**RA-16**](#ra-16-otel-unwire-limitation) | Lifecycle | `_unwire_otel` cannot truly unwire (OTel `set_tracer_provider` is one-shot per process). Currently silent; document the limitation OR fail loud on the second bootstrap with `OtelSettings.enabled=True` | S | ✅ closed |
| [**RA-17**](#ra-17-bootstrap-buffer-flush-formatter) | Diagnostics | `_BootstrapLogBuffer.flush_to_stderr` has no formatter; operator sees stripped records when bootstrap fails | S | ✅ closed |
| [**RA-18**](#ra-18-v0330-doc-drift-cleanup) | Documentation | Multiple modules (`_identity.py`, `_warnings.py`, `HostEnvironmentError` docstring, etc.) still reference removed names (`configure`, `make_settings_config`, `EnvironmentError` alias) | S | ✅ closed |

### P2 — defer to post-v1.0 (11 items; 2 closed-by-docs)

| ID | One-liner | Effort | Status |
|---|---|---|---|
| RA-19 | `bootstrap_for_test(capture_spans=True)` adds a `SimpleSpanProcessor` per call; OTel SDK has no remove API, so processors accumulate across the session | M | ✅ closed (docs) |
| RA-20 | `JsonFormatter._RESERVED_RECORD_ATTRS` hardcoded; Py 3.13+ adding new `LogRecord` attrs will pollute the JSON schema. Derive the set dynamically from a probe `LogRecord` at module-load time | S | ✅ closed |
| RA-21 | `AppContext.reload()` failure-with-successful-restore leaves the caller's `ctx` reference stale (`._shut_down=True`). Document the contract OR return a fresh `AppContext` | M | ✅ closed (docs) |
| RA-22 | `_maybe_emit_runtime_snapshot` builds the snapshot dict outside try/except; if `settings.model_dump` raises, the global is set but bootstrap raises. Wrap. | S | ✅ closed |
| RA-23 | Secret-clearing in vault (overwrite plaintext after use; document the Python-string limitation) | L | ⏳ v1.1+ — Python-string immutability makes secret-clearing largely cosmetic; ctypes-based overwrite is a hardening exercise without a clear v1.0 threat |
| RA-24 | Mutation testing pass (`mutmut` / `cosmic-ray`) on `_lifecycle.py` + `redaction.py` + `_well_known.py` | L | ⏳ v1.1+ — mutation testing infrastructure work; 1411 unit tests + integration tests already provide v1.0 confidence |
| RA-25 | Nightly fuzz corpus for the codemod (`mgf-fed migrate`) — random Python files, assert idempotent + no parse errors | M | ⏳ v1.1+ — fuzz harness is post-v1.0 hardening; the codemod's existing test suite covers the common shapes |
| RA-26 | `mgf-common self-doctor` subcommand — runs against an installed package, reports drift between manifest and runtime | M | ⏳ v1.1+ — diagnostic feature, not a correctness blocker for v1.0 |
| RA-27 | Cross-platform CI matrix (Windows + macOS in addition to Linux) | M | ⏳ v1.1+ — CI infrastructure work; v1.0 ships Linux-first with documented platform support |
| RA-30 | **LG-15 / LG-16 retrofit** — ~9 remaining `_LOG.warning(...)` sites without `event=` / structured `extra={...}` fields (post-LG-15/16 introduction in v2.4): `otel_setup.py:98`, `otel_setup.py:159`, `logging_setup.py:298`, `versioned/_store.py:272`, `process/_run.py:451`, `cli/_handler.py:179`, `cli/_handler.py:187`. Each WARN should land an alert-target `event` name + structured WHY fields per LG-16. The crash_reporter sites were already retrofitted in the 2026-05-15 standards audit (commit pending). Effort: S — one careful pass, ~9 sites + EVENTS.md catalogue additions. | S | ✅ closed |
| RA-31 | **Empty federation-extraction namespace dirs** — `src/mgf/common/db/`, `src/mgf/common/django/`, `src/mgf/common/alembic/` exist with zero `.py` files (only stale `__pycache__/`). Artefacts of v0.30/v0.31 sibling extractions; not import-targets. Remove at the next MAJOR boundary or before, depending on whether old consumers' `import mgf.common.db` deprecation cycle has fully elapsed. Effort: S — verify no consumer references via `mgf-fed catch-up` audit; remove dirs; one cutover-guide entry. | S | ✅ closed |

---

## §3 Invariants we hold

Short list, links to the canonical statements in
[`mgf-standard/docs/standards/`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/). These are load-bearing; reliability
work either preserves them or escalates to the standard owner.

- **AP-03** — 0.x window pin discipline: one MINOR at a time. Every
  RA-* item touching sibling pins respects this (see
  [RA-05](#ra-05-dependency-upper-bounds)).
- **AP-12** — Deprecation cycle: one MINOR with `MgfDeprecationWarning`
  before removal. The v0.33.0 chapter just exercised this end-to-end;
  [RA-18](#ra-18-v0330-doc-drift-cleanup) is the doc cleanup left
  behind by that cycle.
- **CF-04** — Config files: atomic write (temp + rename) at mode 0o600.
  [RA-01](#ra-01-systemic-atomic-write-helper) addresses three sites
  where this standard is inconsistently applied.
- **DP-01** — Strict layering. `bootstrap()` and observability live at
  L4; touching invariants here cannot pull in higher-layer concerns.
- **DP-11** — Every async task has an explicit owner. The streamer
  thread in [RA-07](#ra-07-streamer-thread-exception-visibility) is
  the canonical worry here.
- **DP-12** — UTC at every boundary. Already enforced by ruff DTZ rules.
- **DP-13** — Every owned resource released deterministically.
  [RA-06](#ra-06-process-reap-pin) is the test gap; the implementation
  already obeys.
- **LG-04** — Sensitive fields redacted at the formatter.
  [RA-12](#ra-12-redactor-pattern-coverage-property-test) closes the
  empirical gap in the BUILTIN value-pattern coverage.
- **LG-12** — Per-record logging < 100 µs. Pinned;
  [RA-11](#ra-11-perf-pins-beyond-lg-12) extends the discipline.
- **SC-01** — Secrets live in a vault. [RA-01](#ra-01-systemic-atomic-write-helper)
  is the durability invariant under the SC-01 promise.
- **SC-05** — Vault crypto profile (PBKDF2 600k iterations, Fernet,
  0o600). Preserved; the atomic-write helper in RA-01 doesn't touch
  the crypto layer.
- **TS-04** — `filterwarnings = ["error"]`. Already wired; RA-18's
  doc cleanup doesn't change the policy.
- **TS-06** — Coverage ≥ 80% project-wide. Currently uncommitted in
  CI; [RA-08](#ra-08-coverage-fail_under) wires the gate.

---

## §4 Work units

> One section per row. Each entry has: **Why**, **Concrete output**,
> **Dependencies**, **Status**.

### RA-01 Systemic atomic-write helper

**Why:** Three files implement "atomic write to a path" with three
different patterns. Only one is correct.

| File | fsync? | Notes |
|---|---|---|
| [`vault/_file_vault.py:320-325`](../../src/mgf/common/vault/_file_vault.py#L320) | ❌ | Comment claims fsync; code does NOT call it |
| [`observability/crash_reporter.py:135-145`](../../src/mgf/common/observability/crash_reporter.py#L135) | ❌ | No fsync; no comment claiming there is |
| [`versioned/_store.py:404-424`](../../src/mgf/common/versioned/_store.py#L404) | ✅ file | Calls `os.fsync(fh.fileno())`. Does NOT fsync the parent dir, so the rename itself can be lost on power failure |

The vault is the **last line of defence** for credentials. A vault
that loses keys on unclean shutdown causes a silent loss-of-trust
class of bug: the consumer can't decrypt anything, has no error to
catch, and the only recovery path is a key re-derivation flow that
itself might depend on the lost vault. Crash reports are less
critical, but still: a crash report is exactly the kind of file you
care about *after* a power event, not before.

This is a single-pattern bug across three sites. Fix it once by
extracting a shared helper.

**Concrete output:**
- New `mgf.common.io.atomic_write(path: Path, content: bytes | str,
  *, mode: int = 0o600, fsync_dir: bool = False) -> None` (or
  similar). Internal name (leading `_` or under
  `_internal/`); not part of the public surface for v1.0.
- Sequence: open with `tempfile.mkstemp` in the target's parent dir
  → write → `flush()` → `os.fsync(fh.fileno())` → close → chmod →
  `os.replace(tmp, path)` → if `fsync_dir`, fsync the parent dir
  for full-rename durability.
- Three call sites migrated:
  - `_file_vault._save_store` — `fsync_dir=True` (durability matters).
  - `crash_reporter._write_local` — `fsync_dir=False` (one lost report is acceptable).
  - `versioned/_store._write_atomic` — promoted to call the helper; gains `fsync_dir=True` for the config-rewrite use case.
- A test that wraps `os.fsync` and asserts it was called between
  write and rename for each call site.
- An optional test using `dm-flakey` or a similar fault-injection
  shim to assert the file is recoverable after a simulated crash
  mid-write. (S effort to wire; M to verify across kernels — keep
  it skip-on-CI until cross-platform CI lands per RA-27.)
- The comment lie in `_file_vault.py:320` is fixed (or deleted —
  the helper's docstring documents the invariant).

**Dependencies:** none.

**Status:** ✅ closed (commit 7a69110, 2026-05-12). Effort: M.

---

### RA-02 Rollback chain failure-injection test

**Why:** [`_bootstrap_inner`](../../src/mgf/common/_lifecycle.py#L606)
appends each wiring step's rollback closure to `wiring.rollbacks`,
then on any exception unwinds the list LIFO at
[lines 747-757](../../src/mgf/common/_lifecycle.py#L747). The path
is exercised by exactly ONE test
([`test_bootstrap_failure_rolls_back_partial_state`](../../tests/unit/test_lifecycle.py#L256))
that injects a failure at the OTel step.

What is NOT tested: the chain where a **rollback closure itself
raises**. Line 753-757 prints the rollback failure to stderr and
moves on, but there's no test proving that, say, "OTel wiring
fails → logging rollback ALSO raises → identity rollback still
runs and identity ends up at the placeholder default". The test at
line 256 assumes every rollback succeeds.

If the unwind chain breaks midway and leaves partial state behind
(e.g., the excepthook installed but identity not rolled back), the
bug is invisible until a consumer hits it in production. v1.0's
"transactional bootstrap" promise needs evidence.

**Concrete output:**
- A test that monkeypatches one wiring step (say,
  `mgf.common.observability.otel_setup._wire_otel`) to raise, AND
  simultaneously monkeypatches one earlier rollback closure (say,
  `_unwire_logging`) to also raise.
- Asserts that the FINAL state is rolled back (identity placeholder,
  no global context, root logger handlers restored to pre-bootstrap
  state) — i.e., both rollbacks ran even though one of them threw.
- Asserts the `BootstrapError` carries the original `_wire_otel`
  cause, not the `_unwire_logging` exception.
- Asserts stderr received a "rollback 'logging' failed: …" line
  (line 754-757 in `_lifecycle.py`).

**Dependencies:** none. The fixture for this test will also be
used by [RA-03](#ra-03-concurrent-bootstrap-on-logging-stack).

**Status:** ✅ closed (commit 1d26f64, 2026-05-12). Effort: M.

---

### RA-03 Concurrent bootstrap on logging stack

**Why:** [`_RELOAD_LOCK`](../../src/mgf/common/_lifecycle.py#L91) is
used by [`AppContext.reload`](../../src/mgf/common/_lifecycle.py#L322)
at line 359 to serialise re-wiring. It is **not** held by the
initial `bootstrap()` path or by `_bootstrap_inner` — they run
unsynchronised. Two threads calling `mgf.common.bootstrap(...)`
simultaneously (e.g., a plugin and the host app, or two test
fixtures racing) hit `logging.root.addHandler()` /
`removeHandler()` without synchronisation. Python's `logging`
module is not internally thread-safe for handler-list mutations.

The symptom in the wild is subtle: one of the handlers wins, the
other's records vanish, or duplicate handlers attach and every
record logs twice. Test runners and notebooks are the most likely
trigger.

**Concrete output:**
- Acquire `_RELOAD_LOCK` (or rename to `_BOOTSTRAP_LOCK` to reflect
  the broader role) in `bootstrap()` around the wiring + identity-set
  sections.
- A test that spawns two threads, both calling `bootstrap()` with
  different identities, then asserts the surviving state matches
  exactly ONE of the two threads' inputs (no half-from-A + half-from-B
  state). The serial counterpart of [RA-02](#ra-02-rollback-chain-failure-injection-test)
  test harness.
- Document the contract in the `bootstrap()` docstring: bootstrap
  is serialised; concurrent calls from threads are safe but only
  one wins (last-call-wins, matching the idempotency semantics
  already documented at §14.10 of `FEEDBACK.md`).

**Dependencies:** [RA-02](#ra-02-rollback-chain-failure-injection-test).

**Status:** ✅ closed (commit bb34102, 2026-05-12). Effort: M.

---

### RA-04 `_yaml_file_override` ClassVar concurrency

**Why:** [`BaseAppSettings._yaml_file_override`](../../src/mgf/common/config/_settings.py#L163)
is a class-level attribute (`ClassVar[Path | None] = None`) that
[`load_settings`](../../src/mgf/common/config/_loader.py) sets,
constructs the instance, then resets. Two threads calling
`load_settings(MySettings, ...)` concurrently can race: thread A
sets the override → thread B sets a different override → thread A
constructs (reads B's override) → thread A clears → thread B
constructs (reads None or wrong default).

The bug is silent: config loads succeed, but the loaded values are
from the wrong file. Tests that fixture-isolate via
`_yaml_file_override` on the same subclass are also at risk if
pytest-xdist runs them in parallel within a single worker.

**Concrete output:**
- A reentrant lock or `threading.Lock` around the
  set/construct/clear sequence in `load_settings`.
- A test using `threading.Thread` (or `ThreadPoolExecutor`) that
  loads two different YAML files against the SAME Settings subclass
  concurrently, then asserts the resulting two instances each carry
  values from their respective YAMLs.
- Optionally: a deprecation note that suggests instance-level
  overrides via a constructor arg, with the ClassVar staying as the
  backward-compatible path.

**Dependencies:** none.

**Status:** ✅ closed (commit e9aa46d, 2026-05-12). Effort: M.

---

### RA-05 Dependency upper bounds

**Why:** [`pyproject.toml:38-42`](../../pyproject.toml#L38) declares:

```toml
dependencies = [
    "pydantic>=2.6",
    "pydantic-settings>=2.2",
    "pyyaml>=6.0",
]
```

All three are floor-only. The day pydantic 3.0 lands, `pip install
mgf-common` pulls it in, and every consumer of every sibling sees
breakage they didn't cause. Pydantic in particular has a strong
history of breaking changes at MAJORs.

This is one of the few places where "0.x discipline" (rule AP-03 —
pin one minor at a time) extends downward to direct dependencies.

**Concrete output:**
- Floors bumped to currently-tested versions; upper bounds set at
  the next MAJOR:
  ```toml
  "pydantic>=2.6,<3",
  "pydantic-settings>=2.2,<3",
  "pyyaml>=6.0,<8",
  ```
- Same discipline applied to `[project.optional-dependencies]` rows
  where missing (audit each extras group — `observability`,
  `vault`, `dev`).
- A short recipe doc describing how to test against the
  pre-release of the next MAJOR ahead of cutting the bound (e.g.,
  `uv pip install --prerelease=allow pydantic`).

**Dependencies:** none.

**Status:** ✅ closed (commit ded045c, 2026-05-12). Effort: S.

---

### RA-06 Process reap pin

**Why:** [`_terminate()`](../../src/mgf/common/process/_run.py#L354)
sends SIGTERM → waits `grace_s` → SIGKILL → waits 2 s. The final
wait at [line 394-397](../../src/mgf/common/process/_run.py#L394)
catches `subprocess.TimeoutExpired` and **returns silently**:

```python
try:
    proc.wait(timeout=2.0)
except subprocess.TimeoutExpired:
    pass
```

If SIGKILL fails to reap within 2 s (extremely rare but real on
overloaded hosts, certain container runtimes, or kernels under
heavy I/O), the function returns with the child either still alive
OR a zombie waiting on the kernel. The caller has no idea the child
is in trouble — no log, no exception, no warning.

Under sustained stress (a service repeatedly timing out child
processes), zombies accumulate until the parent hits
`RLIMIT_NPROC`. Worse, the lingering child holds open whatever
resources it held when killed (network sockets, file locks,
shared-memory segments).

**Concrete output:**
- A WARNING-level log at [line 394-397](../../src/mgf/common/process/_run.py#L394)
  when the final wait times out, naming the pid + command_id so
  the operator can correlate.
- A test that launches `sleep 10`, calls `_terminate()` with a
  short grace, then probes (via `os.kill(pid, 0)` raising
  `ProcessLookupError`, or via `psutil.pid_exists(pid)` returning
  False) that the process is gone.
- A second test that repeats the launch+terminate cycle 100×
  and asserts the parent's open-file-descriptor count is stable.
- If `psutil` is preferred for cross-platform: gate it behind a
  `[dev]` extra and skip the test on platforms without it.

**Dependencies:** none.

**Status:** ✅ closed (commit 0ad64a2, 2026-05-12). Effort: M.

---

### RA-07 Streamer thread exception visibility

**Why:** [`_StreamCapture._pump`](../../src/mgf/common/process/_streamer.py#L115)
runs in a daemon thread, draining a child process's stdout/stderr.
The `for raw_line in iter(self._stream.readline, b""):` loop at
line 122 is inside a `try/finally` that closes the stream, but the
loop body itself has no exception handling. If `readline()` raises
mid-stream (BrokenPipeError under SIGPIPE, OSError on a closed fd,
UnicodeDecodeError isn't possible here because decode uses
`errors="replace"`), the exception escapes `_pump`, the thread dies
silently, and any subsequent output from the child is lost.

This is DP-11 territory: the streamer thread has no explicit owner
to observe its death. The parent (`run_command`) joins with a 2s
timeout at line 233-237; if the thread died early, the join
returns immediately and the parent doesn't notice.

**Concrete output:**
- Wrap the loop body in `try / except Exception as e: LOG.warning(...)`
  so a transient read failure is logged with the child's pid +
  stream kind, and the loop can break cleanly if the stream is
  truly gone.
- A test that monkeypatches the child's stream to raise
  BrokenPipeError on the second `readline()` call and asserts: (a)
  the streamer thread ends cleanly, (b) a WARNING-level log record
  was emitted naming the pid + stream.
- Document the behaviour in the `_StreamCapture` docstring.

**Dependencies:** none.

**Status:** ✅ closed (commit 3045016, 2026-05-12). Effort: S.

---

### RA-08 Coverage `fail_under`

**Why:** [`pyproject.toml`](../../pyproject.toml) declares
`[tool.coverage.run]` and `[tool.coverage.report]` but neither
includes a `fail_under = N` threshold. CI runs `pytest --cov` and
reports a number, but a 5% drop is invisible until someone reads
the output. The cookiecutter template that ships with the project
has `fail_under = 80`
([`templates/cookiecutter-mgf-project/.../pyproject.toml:93`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/templates/cookiecutter-mgf-project/%7B%7Bcookiecutter.project_slug%7D%7D/pyproject.toml#L93));
the project itself doesn't eat its own dog food.

**Concrete output:**
- Add `fail_under = 85` (or the current measured coverage minus a
  small margin) under `[tool.coverage.report]`.
- A short note in `docs/standards/TESTING.md` (or the analogous
  doc) that the threshold is raised, never lowered, and that the
  way to clear a regression is to add tests, not loosen the gate.

**Dependencies:** none.

**Status:** ✅ closed (commit 0467367, 2026-05-12). Effort: S.

---

### RA-09 `process_group` on Windows warning

**Why:** [`run_command`](../../src/mgf/common/process/_run.py)
accepts `process_group: bool = True`. On Linux, `True` uses
`start_new_session=True` so the child + every grandchild is
reachable by `killpg()`. On Windows, the check at
[`_terminate` line 368](../../src/mgf/common/process/_run.py#L368) —
`process_group and hasattr(os, "killpg")` — is False, so the path
falls through to `proc.terminate()`, which doesn't cascade. A
consumer running `docker compose up` on Windows will leave
grandchildren orphaned without any warning.

The DP-13 (deterministic resource release) invariant is technically
honoured for the named child, but consumers expect the documented
"cascade kill" semantics across platforms.

**Concrete output:**
- A one-time WARNING (or a `MgfPlatformLimitation` `UserWarning`
  subclass) emitted at first `run_command(..., process_group=True)`
  call on Windows.
- The `process_group` parameter docstring carries an explicit note:
  "On Windows, `process_group=True` is a best-effort no-op; only the
  direct child is killed."
- A test that monkeypatches `sys.platform = "win32"` and asserts the
  warning fires.

**Dependencies:** none.

**Status:** ✅ closed (commit cfcd716, 2026-05-12). Effort: S.

---

### RA-10 `PUBLIC_API.md` vs source lint

**Why:** [`PUBLIC_API.md`](../../PUBLIC_API.md) is the human-readable
contract; [`PUBLIC_API.json`](../../PUBLIC_API.json) is a generator
artifact pinned by `tests/unit/test_public_api_json_pin.py`. The
JSON catches a real category of drift (the generator's view vs the
committed file). But the .md file is hand-written: a typo in a
function signature, a missing row for a newly-added stable name, or
a stale "deprecated" marker can sit there for releases.

The drift just bit us during the v0.33.0 cycle (the
`EnvironmentError` notes section needed manual cleanup;
[RA-18](#ra-18-v0330-doc-drift-cleanup) tracks the rest). A lint
rule that compares the .md's claims against the actual source
`__all__` + `__init__.py` re-exports would catch this class.

**Concrete output:**
- A test (or `mgf-common` subcommand) that parses `PUBLIC_API.md`,
  extracts the name list under each module heading, and compares
  against the import-time `__all__` of the corresponding source
  module. Fail on mismatch.
- Tolerated drift: types that are documented but not in `__all__`
  (warnings, dataclasses, type aliases) need an explicit allowlist.

**Dependencies:** none.

**Status:** ✅ closed (commit 4b6d394, 2026-05-12). Effort: S.

---

### RA-11 Perf pins beyond LG-12

**Why:** the file-sink logging pin
([`tests/perf/test_perf_pins.py::TestFileSinkLoggingPerf`](../../tests/perf/test_perf_pins.py))
pins per-record logging cost baseline-relative (PF-01; it was an absolute
100 µs budget until the perf suite migrated to relative baselines). That's
one surface. The
library has at least four more hot paths where a silent perf
regression would matter:

1. **`bootstrap()`** — the cold-start cost; consumer apps pay this
   on every CLI invocation.
2. **`Redactor.redact_string`** — runs on every log record and every
   captured subprocess line; even a 50 µs regression compounds.
   The PEM regex uses `re.DOTALL` and can be slow on long inputs.
3. **`JsonFormatter.format`** — same multiplier as redaction.
4. **`current_context()`** — claimed in `PUBLIC_API.md` to be
   ~30 ns; not pinned by a test.

A perf regression here is the kind of bug that doesn't break tests
but makes consumers' apps slower release-over-release in ways
nobody attributes to the library.

**Concrete output:**
- Four small perf tests, each with a generous budget (current
  measurement × 2 or × 3 to avoid CI flakiness), mirroring the
  shape of LG-12.
- Document each budget in the corresponding standard
  (`PERFORMANCE.md` if it exists, otherwise add inline rule notes).
- A nightly-only `pytest -m perf` marker so the perf tests don't
  inflate the standard suite.

**Dependencies:** none.

**Status:** ✅ closed (commit 5ea6df3, 2026-05-12). Effort: M.

---

### RA-12 Redactor pattern coverage property test

**Why:** The Redactor already has property-based tests
([`test_redaction_property.py`](../../tests/unit/observability/test_redaction_property.py))
that pin the GENERAL guarantee — redacting a payload N times equals
redacting once. What's missing is **per-pattern coverage** proof:
the redactor's
[`_BUILTIN_VALUE_PATTERNS`](../../src/mgf/common/observability/redaction.py#L107)
claims to catch Bearer / JWT / PEM / OpenAI / GitHub / AWS / Slack /
Google formats — but there's no test that generates a hundred
valid instances of each format and asserts the redactor catches
them.

If a pattern's regex has a subtle bug (e.g., misses a hyphen
position, fails on lowercase variants, doesn't anchor on word
boundaries correctly), today's tests pass and the secret silently
appears in logs.

**Concrete output:**
- A `tests/unit/observability/test_redaction_value_patterns.py`
  using hypothesis to generate valid samples of each named format
  in `_BUILTIN_VALUE_PATTERNS`.
- For each format: a list of NEGATIVE examples (look-alike strings
  that MUST NOT be redacted — e.g., a public AWS resource ARN that
  happens to contain `AKIA` not as an access key).
- Document the coverage in `SECURITY_STANDARD.md` §15.

**Dependencies:** none.

**Status:** ✅ closed (commit 1e02f5d, 2026-05-12). Effort: M.

---

### RA-13 `AppConfigErrorKind.MIGRATE_FAILED` unused

**Why:** [`AppConfigErrorKind`](../../src/mgf/common/exceptions/_well_known.py)
is a `StrEnum` discriminator on `AppConfigError`, with
`MIGRATE_FAILED` listed as one of its values. A grep across the
codebase finds the constant defined but never **raised** — every
`AppConfigError` raise site either uses a different kind or
doesn't set `kind` at all.

Consumers relying on `match e.kind:
case AppConfigErrorKind.MIGRATE_FAILED:` can't actually catch
migration failures via the discriminator. The contract is
technically honoured (the enum exists), but it's a dead branch.

**Concrete output:**
- Audit `mgf.common.versioned` / `mgf.common.config` for migration
  call sites; set `kind=AppConfigErrorKind.MIGRATE_FAILED` when a
  migration callback raises.
- Add a test that triggers migration failure and asserts the kind.
- If the enum value is intentionally reserved for a future path,
  document that explicitly in the enum's docstring.

**Dependencies:** none.

**Status:** ✅ closed (commit e1d9093, 2026-05-12). The first-pass
audit claim was partially wrong: `MIGRATE_FAILED` IS already set
in `mgf.common.versioned._store._store.py:330` (the
`VersionedFileStore` migrate path). What WAS missing was the
parallel path in `mgf.common.config._loader.load_settings` —
where consumer migrate callbacks could raise an uncaught exception
that propagated to the caller bypassing `AppConfigError` entirely.
The fix wraps `migrate(raw, version)` in a try/except that
re-raises as `AppConfigError` with
`kind=AppConfigErrorKind.MIGRATE_FAILED`. While there, every other
loader raise gained an appropriate `kind`
(YAML_PARSE_FAILURE / NON_DICT_ROOT / MISSING_VERSION /
UNSUPPORTED_VERSION). Effort: S.

---

### RA-14 Cross-platform config paths test (Windows)

**Why:** [`config/_paths.py`](../../src/mgf/common/config/_paths.py)
has Linux / macOS / Windows branches for XDG-style path resolution.
The Linux + macOS branches are tested directly. The Windows branch
is "tested" by code review and `mypy` — there's no
`monkeypatch.setattr(sys, "platform", "win32")` test that
exercises the actual branch. Existing tests do mock `os.name` for
some Windows checks, but coverage is partial.

mgf-common doesn't currently run CI on Windows (
[RA-27](#2-priority-table) tracks adding that); the federation
roadmap doesn't promise Windows as a first-class platform. But the
helpers DO contain Windows-specific code, and if it's wrong, the
first time we notice will be when a consumer runs on Windows.

**Concrete output:**
- Targeted unit tests with `monkeypatch.setattr(sys, "platform",
  "win32")` covering each Windows branch in `_paths.py` (config /
  state / data / log paths).
- Use `monkeypatch.setenv` to set / unset `APPDATA`,
  `LOCALAPPDATA`, and assert the helpers produce well-formed
  paths.
- One end-to-end test using a `pathlib.PureWindowsPath` to
  validate paths can be `__fspath__`'d on a Windows-shaped string
  without surprises.

**Dependencies:** none.

**Status:** ✅ closed (commit 8b666ba, 2026-05-12). Effort: M.
The first-pass audit's claim that Windows branches were
"tested only by code review" was partially wrong: the
existing tests at `test_paths.py:80-105` already cover three of
the four Windows branches (config-via-APPDATA, state-via-LOCALAPPDATA,
fallback-to-USERPROFILE). RA-14 adds the missing pieces:
`data` kind on Windows, XDG-override-wins-on-Windows-for-every-kind,
and a `PureWindowsPath` round-trip pin on the path-string shape.
Also surfaced (but NOT fixed here — separate follow-up): the
state-dir helpers in `mgf.common.observability.paths` hardcode
`~/.local/state` and don't use `platform_dir`, so logs + crash
reports on Windows land in a Linux-shaped path rather than the
expected `%LOCALAPPDATA%`. Track that as a future RA-* if a
Windows consumer surfaces.

---

### RA-15 Bootstrap replace semantics

**Why:** When `bootstrap()` is called while a prior context is
active, [lines 586-599 of `_lifecycle.py`](../../src/mgf/common/_lifecycle.py#L586)
log an AUDIT record AND **immediately** tear down the prior
context BEFORE re-wiring:

```python
if _GLOBAL_CONTEXT is not None:
    prior = _GLOBAL_CONTEXT
    LOG.warning("bootstrap called again; replacing existing context", ...)
    prior.shutdown()

return _bootstrap_inner(app_name, app_version, settings, ...)
```

Two real failure modes:

1. **`_bootstrap_inner` raises after `prior.shutdown()`.** The
   process is left with NO context: `prior` is shut down (its
   wiring rolled back), and the new bootstrap rolled back its own
   wiring on failure. The next caller of `current_context()` gets
   `None`. The next `app_name()` reads the module-global
   placeholder and emits `UnconfiguredWarning`. There's no rollback
   to a working state.

2. **The "bootstrap.replace" AUDIT log goes nowhere visible.** The
   `LOG.warning(...)` at line 588 happens BEFORE `prior.shutdown()`,
   so prior handlers are still wired and the AUDIT lands. But the
   bootstrap-log-buffer for the NEW bootstrap hasn't been installed
   yet, and `_bootstrap_inner` is about to install fresh handlers
   that don't see this record. In edge cases (the prior context
   had `setup_logging=False`), the AUDIT log lands on the consumer's
   framework-owned logging — visible — but the operator may not
   know to look there.

The current shape optimises for the happy path (replace works);
v1.0 wants the failure path to leave the prior context standing.

**Concrete output:**
- Re-order: `_bootstrap_inner(...)` runs FIRST (with its own rollback
  on failure). On success, ONLY THEN tear down the prior context.
- A test that monkeypatches `_bootstrap_inner` to raise after
  `prior.shutdown()` is called and asserts the prior context is
  still active (its `_shut_down` is False; `current_context()`
  returns it).
- Document the new contract in `bootstrap()`'s docstring: "On
  re-bootstrap, the prior context is preserved if the new
  bootstrap fails."

**Dependencies:** none.

**Status:** ✅ closed (commit 2dd89d4, 2026-05-12). Effort: S. The
fix also discovered that the chain-forward of `prior_*` snapshots
through replace is required: without it, the new context's
`shutdown()` would restore in-between state (the prior context's
hook / identity) rather than the pre-bootstrap state. Two tests
land with this commit:
`test_replace_chains_pre_bootstrap_state_forward` and
`test_failed_replace_leaves_prior_context_active`.

---

### RA-16 OTel unwire limitation

**Why:** [`_unwire_otel`](../../src/mgf/common/_lifecycle.py#L848)
admits in its docstring that OTel's `TracerProvider` cannot be
reset to a no-op cleanly — `set_tracer_provider` is one-shot per
process. The current implementation shuts down the provider so its
batch processor flushes, but the provider remains set. Any
subsequent `bootstrap()` that tries to wire a different
TracerProvider silently no-ops.

The symptom: in a process that bootstraps twice (e.g., a test
session, a notebook, a plugin host), spans from the second
bootstrap may go to the first bootstrap's exporter — or to the
shut-down provider, where they vanish.

The library accepts this as a known platform limitation, but
nothing tells the caller. A `OnceWarning` at the second-bootstrap-
with-different-otel-config call site would close the visibility gap.

**Concrete output:**
- Detect at `_wire_otel` entry: if a non-no-op `TracerProvider` is
  already set AND the new settings request a different
  configuration, emit a `MgfPlatformLimitation` UserWarning naming
  the limitation (with a docs link).
- Document in `bootstrap()`'s docstring: "OTel wiring is one-shot
  per process; subsequent bootstraps with different `OtelSettings`
  inherit the first wiring".
- A test that bootstraps with otel A, then otel B, and asserts the
  warning fires.

**Dependencies:** none.

**Status:** ✅ closed (commit 9f0120d, 2026-05-12). Effort: S.

---

### RA-17 Bootstrap buffer flush formatter

**Why:** When bootstrap fails, the
[`_BootstrapLogBuffer.flush_to_stderr`](../../src/mgf/common/_lifecycle.py#L432)
method dumps captured records to stderr. The buffer was never
given a formatter (`self.formatter is None`), so the flush falls
back to `record.getMessage()` at line 439:

```python
msg = self.format(record) if self.formatter else record.getMessage()
sys.stderr.write(f"[mgf.common bootstrap] {msg}\n")
```

The operator sees the *message text* but NOT the level, logger
name, or timestamp. For a bootstrap that fails midway, the
sequence of records IS the diagnostic: "level=INFO bootstrap
started → level=INFO wiring logging → level=ERROR logging failed:
permission denied". With no level/logger prefix, that read is
lossy.

**Concrete output:**
- Assign a minimal formatter to the buffer at construction
  ([line 407-409](../../src/mgf/common/_lifecycle.py#L407)):
  `logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")`.
- A test that triggers a bootstrap failure, captures stderr, and
  asserts the level + logger name appear in the flushed line.

**Dependencies:** none.

**Status:** ✅ closed (commit 1c38a43, 2026-05-12). Effort: S.

---

### RA-18 v0.33.0 doc drift cleanup

**Why:** The v0.33.0 release removed three deprecated names
(`configure`, `make_settings_config`, `EnvironmentError` alias).
Source code references are clean — but several **docstrings**
across the library still reference these names as if they were
live:

- [`_identity.py:1-7`](../../src/mgf/common/_identity.py#L1) —
  module docstring: "Set once at startup via
  `mgf.common.configure`".
- [`_identity.py:16`](../../src/mgf/common/_identity.py#L16) —
  "every production caller MUST call `mgf.common.configure`".
- [`_identity.py:39-41`](../../src/mgf/common/_identity.py#L39) —
  "Tracks whether configure() has been called this process.
  Reading identity ... before configure() emits…"
- [`_identity.py:64-69`](../../src/mgf/common/_identity.py#L64) —
  `_set_identity`'s docstring still claims "Used by ... so the
  new path is silent; public `configure` wraps this AND warns".
- [`_warnings.py:5-7, 35-44`](../../src/mgf/common/_warnings.py#L5)
  — docstring still lists `configure` /
  `make_settings_config` / `EnvironmentError` as live migration
  shims.
- [`exceptions/_well_known.py:256-260`](../../src/mgf/common/exceptions/_well_known.py#L256)
  — `HostEnvironmentError` docstring claims "The legacy name
  remains as a deprecated alias that emits
  `MgfDeprecationWarning`" — the legacy name no longer exists.

This is a small commit, but the drift matters: future AI agents
(this one included) read these docstrings as ground truth and
either misadvise consumers or waste cycles verifying claims that
turn out to be stale.

**Concrete output:**
- Sweep every file under `src/mgf/common/` for the substrings
  `configure`, `make_settings_config`, `EnvironmentError`. For
  each match: keep where it's part of an explanatory v0.33.0
  cutover narrative; rewrite where it's stated as a live API claim.
- Same sweep across `docs/` (the AI-guide `CLAUDE.md` was already
  swept; the rest of `docs/` likely has similar drift).
- A grep-based CI check: `grep -rn 'mgf\.common\.configure\b'
  src/ docs/` fails if it finds anything not in an allowlisted
  cutover/historical file.

**Dependencies:** none.

**Status:** ✅ closed (commit f0f16dc, 2026-05-12). Effort: S.

---

## §5 Closed items

- **RA-21** — `AppContext.reload()` failure-with-restore
  contract now documented inline on `reload()`'s docstring
  (`_lifecycle.py:359-419`). The behaviour stays the same — a
  failed reload that successfully restores STILL leaves the
  caller's `ctx` reference flagged `_shut_down=True`, because
  `reload()` calls `self.shutdown()` BEFORE the new wiring
  attempt; the audit decision was to document rather than
  switch to "return a fresh AppContext from the restore path"
  because the API-shape change would surprise callers who DON'T
  catch `BootstrapError` (they'd never see the swap) and the
  recovery pattern via `current_context()` is straightforward.
  Docstring now spells out the recovery shape (`ctx =
  mgf.common.current_context()` after catching the re-raised
  `BootstrapError`) plus the unrecoverable case (restore also
  fails → `current_context()` returns `None` → re-`bootstrap()`
  or exit). Doc-only — no behaviour change, no new tests
  needed. (commit pending, 2026-05-15).
- **RA-19** — `bootstrap_for_test(capture_spans=True)`
  per-process span-processor accumulation documented inline on
  the `capture_spans` parameter doc in `bootstrap_for_test()`
  (`_test_helpers.py:231-251`). The OTel SDK has no remove API;
  the existing rollback shuts the processor down (post-shutdown
  emits no-op) but the processor object stays in the provider's
  list for the rest of the process. The audit's "M" effort
  estimate assumed an actual implementation fix; reality is the
  constraint is upstream (OTel SDK API surface) and the cost is
  ~N µs per span at N processors — only material for long test
  sessions that call `bootstrap_for_test(capture_spans=True)`
  thousands of times. Docstring now surfaces the constraint at
  the user-facing entry point (was only documented in the
  internal `_wire_span_capture` helper) and points consumers at
  the session-scoped TracerProvider workaround. Doc-only — no
  behaviour change. (commit pending, 2026-05-15).
- **RA-30** — LG-15/16 retrofit complete. The 6 actual
  remaining WARN sites outside crash_reporter (audit-reported
  ~9 — `process/_run.py:451` already had `event=` from a
  prior fix) now carry stable event names + structured WHY +
  actionable HOW hints: `otel.sdk_unavailable` /
  `otel.httpx_instrument_failed` /
  `logging.http_sink.invalid_url` / `versioned.grace_mode` /
  `cli.command_failed` / `cli.unhandled_exception`. All six
  catalogued in `docs/reference/EVENTS.md` (now 21 distinct
  event names total). One test updated to assert on
  structured fields instead of prose substring (the standard
  shift LG-16 implies). 1411 tests pass; mypy --strict clean.
  (commit pending, 2026-05-15).
- **RA-31** — `src/mgf/common/db/`, `/django/`, `/alembic/`
  empty namespace dirs removed. Verified git-tracked nothing
  in them (only stale `__pycache__/` from v0.30/v0.31 sibling
  extractions). No code/tests/examples imported them.
  Filesystem cleanup only — no git diff, just confirmation
  the dirs no longer exist. (Verified by `ls` after
  `rmdir`.)
- **RA-22** — `_maybe_emit_runtime_snapshot` is now wrapped in
  try/except, making the "best-effort" claim in its docstring
  actually true. Before the fix, `bootstrap()` set
  `_GLOBAL_CONTEXT = new_context` (`_lifecycle.py:864`) and THEN
  called the snapshot helper — so any raise from inside
  (a `@computed_field` throwing during `settings.model_dump`,
  file-handle exhaustion on the atomic write, permissions error
  on `MGF_DOCTOR_RUNTIME_PATH`, an import error in the lazy
  `_doctor_live` import) left the process with a fully-wired
  AppContext on the global AND a propagating `BootstrapError` —
  an inconsistent state the caller couldn't recover from
  cleanly. Fix: the entire helper body (dict construction +
  `emit_runtime_snapshot()`) lives inside a try/except that
  logs a WARNING with `audit=true`,
  `event="bootstrap.runtime_snapshot_failed"`, and the
  exception type + message so operators can diagnose. Two new
  tests in `TestRA22RuntimeSnapshotBestEffort`:
  snapshot-failure-does-not-propagate (monkeypatch
  `emit_runtime_snapshot` to raise; assert `bootstrap()`
  returns a usable AppContext + the warning lands on stderr
  with the right event name + error_type), and
  snapshot-success-does-not-warn (sanity: the try/except wrap
  must not mask successful writes). Tests use `capsys` instead
  of `caplog` because `bootstrap()` rewires the root logger's
  handlers to the JSON-to-stderr sink, so `caplog` (attached
  before bootstrap) doesn't see post-bootstrap records. 1415
  tests pass (was 1413 + 2 new); mypy --strict clean.
  (commit `6e991f1`, 2026-05-14).
- **RA-20** — `JsonFormatter._RESERVED_RECORD_ATTRS` is now
  derived at module-load time from a probe `LogRecord`, not
  hardcoded. New `_derive_reserved_record_attrs()` helper
  constructs a `logging.LogRecord` with default args, reads its
  `__dict__` keys, and unions in `message` + `asctime` (which
  are populated by `Formatter.format` / `getMessage`, not by
  `__init__`, so they don't show up in the probe). Future
  Python versions adding new `LogRecord` attributes (the way
  3.12 added `taskName`) get reflected automatically — no
  manual update needed for the JSON formatter to keep ignoring
  them. Four new tests in `TestRA20DynamicReservedAttrs`:
  derived-set-covers-every-init-attr (the probe's keys must all
  be in the reserved set), derived-set-includes-formatter-attrs
  (`message` + `asctime` union pinned), no-spurious-top-level-
  keys-on-plain-record (the user-facing guarantee — a record
  with no `extra={...}` produces only documented keys),
  explicit-extras-still-promote (the derivation must not
  over-reserve). One-time module-load cost (one `LogRecord`
  allocation at import); zero runtime cost on the per-record
  path. 1413 tests pass (was 1409 + 4 new); mypy --strict
  clean. (commit `1085efd`, 2026-05-14).
- **RA-29** — `mgf.common.observability.paths.default_state_dir`
  now composes with `mgf.common.config._paths.platform_dir`
  instead of hardcoding `~/.local/state`. Cross-platform paths
  flow per the existing `platform_dir` mapping:
  Linux stays `XDG_STATE_HOME` or `~/.local/state` (no change);
  macOS now resolves to `~/Library/Application Support/<app>`
  (was: wrong Linux path); Windows now resolves to
  `%LOCALAPPDATA%/<app>` or `<home>/AppData/Local/<app>` (was:
  wrong Linux path). Three new cross-platform tests in
  `tests/public_surface/test_observability_as_user.py::TestPathsCrossPlatform`:
  macOS-state-under-Application-Support, Windows-state-via-
  USERPROFILE-fallback, XDG-override-wins-on-macOS. (Windows-
  LOCALAPPDATA path-of-composition not directly testable on
  Linux due to pathlib's WindowsPath-instantiation rule; the
  branch is unit-tested in `tests/unit/config/test_paths.py`.)
  Five existing Linux tests still pass — Linux behaviour
  unchanged. 1384 total tests pass. (commit e3e9ab7,
  2026-05-12).
- **RA-28** — `mgf.common.config._loader._write_yaml_atomic`
  migrated to the shared `atomic_write` helper from RA-01 (was
  the 4th atomic-write site that RA-01 missed). Body fsync +
  parent-directory fsync now apply (was: neither). YAML
  serialisation happens in-process before the helper call so
  the helper sees a finished string. The `os` and `tempfile`
  imports drop from `_loader.py`; `Path` moves to `TYPE_CHECKING`
  since it's now only a type annotation. 1381 tests still pass.
  (commit 714155b, 2026-05-12).
- **RA-05** — Dependency upper bounds added to core deps + all
  three optional extras + `[dev]`. `pydantic<3` / `pydantic-settings<3`
  / `pyyaml<8` / OTel-family `<2` / sentry-sdk `<3` / keyring `<26`
  / cryptography `<48` / pytest `<10` / mypy `<2` / hypothesis `<7`
  / ruff `<1` / import-linter `<3`. 1318 tests still pass. (commit
  ded045c, 2026-05-12).
- **RA-14** — Four new tests in `tests/unit/config/test_paths.py`:
  `test_windows_data_uses_localappdata`,
  `test_windows_data_falls_back_to_userprofile_appdata_local`,
  `test_windows_xdg_override_wins_for_every_kind`,
  `test_windows_path_strings_roundtrip_via_pure_windows_path`.
  Closes the gap on the `data` kind (3 of 4 branches were
  already covered; the audit was partly wrong about the
  coverage state). Discovered but parked as a separate
  follow-up: `mgf.common.observability.paths` hardcodes
  `~/.local/state` and doesn't compose with `platform_dir` — on
  Windows, logs/crashes land in a Linux-shaped path. 1381 total
  tests pass. (commit 8b666ba, 2026-05-12).
- **RA-12** — New
  `tests/unit/observability/test_redaction_value_patterns.py`:
  8 hypothesis-driven property tests (one per BUILTIN value
  pattern — Bearer/Basic, JWT, PEM, OpenAI, GitHub, AWS, Slack,
  Google) each generates up to 200 valid samples and asserts the
  redactor catches every one. Plus 4 negative tests
  (look-alike strings that MUST NOT be redacted) pin the
  word-boundary discipline against over-eager regexes. Plus a
  cross-pattern sanity test with all 8 formats in one line.
  Surfaced and documented a known limitation: the BUILTIN regexes
  anchor on trailing `\b`, so tokens ending in non-word chars
  (`/`, `=`, `-`) are NOT caught — strategies generate
  word-class-terminated samples to mirror what the regex actually
  catches; consumers needing the wider coverage can compose via
  `MgfSettings.redaction.extra_value_patterns`. 1377 total tests
  pass. (commit 1e02f5d, 2026-05-12).
- **RA-11** — New perf-pin test file
  `tests/unit/test_perf_pins.py` (marker: `perf`) with four
  budgets:
    - `current_context()`: 500 ns (measured ~170 ns)
    - `Redactor.redact_string`: 5 µs (measured ~1.5 µs)
    - `JsonFormatter.format`: 30 µs (measured ~10 µs)
    - `bootstrap()`: 5 ms median over 5 runs (measured ~1.2 ms)
  Each test warms the path with 100 reps then times N reps;
  budget is current × 2-3 to absorb CI noise. New `perf` marker
  declared in `pyproject.toml`; tests run in the default suite
  (loose budgets, low overhead) but can also be isolated via
  `pytest -m perf`. 1364 total tests pass. (commit 5ea6df3,
  2026-05-12).
- **RA-10** — New regression test
  `tests/unit/test_public_api_md_coverage.py` enforces that
  every public name in `PUBLIC_API.json` appears in `PUBLIC_API.md`
  as a backtick-wrapped code-span. Catches the orthogonal drift
  class to the existing JSON pin: "new public name shipped but
  forgot to document it in the human-readable contract". Two
  tests: one walks every JSON-listed name and fails on any not
  documented; the other prevents the allowlist from rotting
  (entries removed from PUBLIC_API.json must be pruned from the
  allowlist). Verified the lint catches drift by injecting a
  fake name. 1360 total tests pass. (commit 4b6d394, 2026-05-12).
- **RA-16** — `_wire_otel` now emits a one-shot
  `MgfPlatformLimitation` warning when a second call with
  `enabled=True` would have tried to install a new
  TracerProvider. New `_REWIRE_WARNED` guard mirrors the RA-09
  pattern. Three new tests
  (`test_warning_fires_on_second_wire_with_enabled`,
  `test_warning_is_one_shot`, `test_no_warning_when_second_call_disabled`).
  Pre-existing `test_setup_otel_idempotent` updated to set
  `_REWIRE_WARNED=True` (testing the idempotency invariant, not
  RA-16's warning). 1358 total tests pass. (commit 9f0120d,
  2026-05-12).
- **RA-09** — New warning class `MgfPlatformLimitation`
  (`UserWarning` subclass) added to `mgf.common._warnings`.
  `run_command(process_group=True)` on Windows now emits this
  warning once per process via a `_WINDOWS_PGROUP_WARNED`
  one-shot guard. Message names the limitation, the cause
  (no `os.killpg` on Windows), and the escape hatch
  (`process_group=False`). Docstring updated. Four new tests:
  fires-on-first-Windows-call, one-shot (second call silent),
  no-warning-on-POSIX, no-warning-when-process_group=False.
  1355 total tests pass. (commit cfcd716, 2026-05-12).
- **RA-07** — `_StreamCapture._pump`'s `readline()` loop now
  catches `Exception` and logs a WARNING with
  `event=process.streamer_read_failure`, `child_pid`, `stream`,
  `error_type`, `error_message`, `command_id` extras. The
  `finally` still closes the stream cleanly. New test file
  `tests/unit/process/test_streamer.py` with 3 tests: failure
  logs WARNING + thread exits cleanly + stream closed; failure
  doesn't propagate to `join()` (and pre-failure lines are
  preserved in the captured snapshot); happy-path EOF exit emits
  NO RA-07 WARNING. 1351 total tests pass. (commit 3045016,
  2026-05-12).
- **RA-13** — `mgf.common.config._loader.load_settings` now wraps
  consumer migrate-callback failures as `AppConfigError` with
  `kind=AppConfigErrorKind.MIGRATE_FAILED`. While there, every
  other loader-side `AppConfigError` raise gained its appropriate
  kind (YAML_PARSE_FAILURE / NON_DICT_ROOT / MISSING_VERSION /
  UNSUPPORTED_VERSION). The first-pass audit was partially wrong:
  the `VersionedFileStore` migrate path at
  `_store.py:330` was already correct; the gap was in the
  parallel `config._loader` path. Five new tests
  (`test_migrate_failure_carries_migrate_failed_kind` +
  `TestLoaderErrorKinds` × 4) pin each kind. 1348 total tests pass.
  (commit e1d9093, 2026-05-12).
- **RA-17** — `_BootstrapLogBuffer.__init__` now attaches a
  minimal formatter
  (`"%(asctime)s %(levelname)-7s %(name)s: %(message)s"`). The
  emergency `flush_to_stderr` path on bootstrap failure now emits
  records with level + logger + timestamp + message. New test
  `test_flush_to_stderr_includes_level_and_logger` synthesises an
  INFO and ERROR record, flushes, asserts both levels + logger
  names + messages appear in stderr alongside the
  `[mgf.common bootstrap]` wrapper prefix. 1343 total tests pass.
  (commit 1c38a43, 2026-05-12).
- **RA-08** — Added `fail_under = 80` to `[tool.coverage.report]`.
  Total coverage measured at 80.19%; gate set at 80% with the
  understanding that future work raises (never lowers) the floor.
  Verified the gate fires: `pytest --cov ... ` now reports
  "Required test coverage of 80.0% reached." (commit 0467367,
  2026-05-12).
- **RA-18** — Doc drift sweep through `src/mgf/common/_identity.py`,
  `_warnings.py`, `_lifecycle.py`, `config/_settings.py`,
  `exceptions/_well_known.py`, `cli/_doctor.py`, plus
  `docs/standards/{API_DESIGN,COMMON_COMPONENTS,CONFIGURATION,README}.md`
  and `docs/claude/CLAUDE.md` — every live reference to removed
  `configure` / `make_settings_config` / `EnvironmentError` names
  rewritten to the post-v0.33.0 canonical names (`bootstrap`,
  `settings_config`, `HostEnvironmentError`). Historical narratives
  in CLAUDE.md updated to note the removal year. New
  `tests/unit/test_v033_drift_guard.py` (3 tests) enforces a small
  allowlist of files where the removed names legitimately appear
  (codemod, catch-up audit, cutover guide, extraction history,
  this tracker, PUBLIC_API.md, CHANGELOG.md); any new occurrence
  outside the allowlist fails CI with a specific file:line +
  rename guide. 1342 total tests pass. (commit f0f16dc,
  2026-05-12).
- **RA-06** — `_terminate()` now logs a WARNING when the final
  2-second `proc.wait` times out (was silent return). `command_id`
  threaded through from `run()` so the log record correlates with
  the originating call. Two new tests:
  `test_pid_is_gone_after_terminate` (captures pid via Popen
  monkeypatch, asserts `os.kill(pid, 0)` raises
  `ProcessLookupError` after `ProcessTimeout` returns — positive
  reap pin); `test_warning_emitted_when_reap_times_out` (stubs
  `proc.wait/terminate/kill` to force the timeout path, asserts a
  single WARNING with `event=process.reap_timeout`, `child_pid`,
  `command_id` extras). 1339 total tests pass. (commit 0ad64a2,
  2026-05-12).
- **RA-03** — `_RELOAD_LOCK` renamed to `_WIRING_LOCK` (broader
  role); now held by `bootstrap()` initial path as well as
  `reload()`. The lock wraps the replace check + AUDIT log +
  `_bootstrap_inner` + prior_* chain-forward. End state under
  concurrent calls: last-call-wins with no mixed wiring. New test
  `test_concurrent_bootstraps_serialize_cleanly` spawns two
  threads via a `Barrier` 25× and asserts (a) no errors, (b)
  `current_context()` is one of the two inputs, (c) the loser is
  marked `_shut_down=True` with empty rollbacks, (d)
  `_identity._APP_NAME` matches the winner. Race confirmed
  without the lock (1 mismatch in 30 iterations). 1337 total
  tests pass. (commit bb34102, 2026-05-12).
- **RA-02** — Test
  `test_rollback_chain_completes_when_a_rollback_step_itself_raises`
  added. Injects synthetic `_wire_otel` failure (step 7) AND a
  failing `_unwire_logging` rollback. Asserts three invariants:
  (a) `BootstrapError` carries the ORIGINAL OTel cause not the
  rollback failure; (b) stderr received a
  "rollback 'logging' failed: …" line so operators can correlate;
  (c) identity rolled back to placeholder despite the
  mid-rollback failure (proves the LIFO loop continued past the
  failing step). 1336 total tests pass. (commit 1d26f64,
  2026-05-12).
- **RA-04** — `_LOAD_SETTINGS_LOCK: threading.RLock` added to
  `mgf.common.config._loader`; wraps the set/construct/clear
  sequence on `settings_cls._yaml_file_override`. Reentrant so a
  Settings `__init__` that recursively calls `load_settings`
  doesn't deadlock. Two new tests: one runs two threads loading
  different YAMLs into the same subclass 50× each and asserts no
  cross-contamination; the other pins the `finally` branch that
  restores the override after construction failure. Verified the
  race exists without the lock (10 contaminations in 400 loads
  with the lock disabled). 1335 total tests pass. (commit e9aa46d,
  2026-05-12).
- **RA-01** — Extracted `mgf.common._io.atomic_write(path, content,
  *, mode=0o600, fsync_dir=False, encoding="utf-8")`. Body always
  fsync'd before rename; parent-directory fsync opt-in for
  files whose lost-rename is load-bearing. Three call sites
  migrated: `vault/_file_vault._save_store` (`fsync_dir=True` —
  vault durability), `observability/crash_reporter._write_local`
  (`fsync_dir=False` — one lost report acceptable),
  `versioned/_store._write_atomic` (`fsync_dir=True` — config
  durability). The vault's misleading "fsync, rename" comment is
  now true. 13 new helper tests covering body, mode, fsync order,
  fsync_dir, failure cleanup, Windows skip. 1333 total tests pass.
  (commit 7a69110, 2026-05-12).
- **RA-15** — Bootstrap replace re-ordered: new wiring runs first;
  prior is marked superseded (`_shut_down=True`, rollbacks cleared)
  only on success. On failure, prior context stays active.
  Discovered during implementation that the `prior_*` snapshots
  must chain forward (otherwise new_context.shutdown() restores
  in-between state instead of pre-bootstrap state); fix carries
  that propagation. Two new tests
  (`test_failed_replace_leaves_prior_context_active`,
  `test_replace_chains_pre_bootstrap_state_forward`); 1320 tests
  total pass. (commit 2dd89d4, 2026-05-12).

---

## §6 Notes on methodology

This tracker was seeded by a breadth audit (v0.1) and refined by a
depth audit (v0.2). The depth audit walked the load-bearing modules
end-to-end (`_lifecycle.py`, `observability/{redaction,
json_formatter,crash_reporter}.py`, `process/_run.py`,
`vault/_file_vault.py`, `versioned/_store.py`, `_identity.py`,
`_warnings.py`, `_test_helpers.py`, `pytest_plugin.py`), reading
critical paths line-by-line rather than relying on grep alone. Each
finding was verified against `file:line` evidence before landing
here; the v0.1 → v0.2 delta is listed at the top of §1.

The shape is deliberately stolen from PlasmaMapper's
`RELIABILITY_AND_ACCURACY.md`: priority table → first wave → work
units. The discipline that makes it work is keeping the items
**narrow** (each one a single concrete commit) and **falsifiable**
(each one has a written "concrete output" that can be checked off).

When an item closes, move it to §5 with a one-line summary and a
commit ref. Don't let items rot in "in progress" — either keep them
small enough to close in one sitting, or split them.

**For future audit passes:** the depth pass found that the breadth
pass missed the systemic patterns. The atomic-write inconsistency
(RA-01) shows up only when you compare the three sites side-by-side;
no single-file grep surfaces it. Future passes should explicitly
look for **patterns across modules** (atomic writes, lock usage,
exception swallowing, doc drift after a deprecation removal) as a
separate phase from the per-module deep-read.
