# Engineering Standards — Master Index

> **Audience:** Human engineers AND AI coding agents.
> **Reference implementation:** [`mgf-common`](https://codeberg.org/magogi-admin/mgf-common) — every standard in this folder is grounded in code that ships in the `mgf-common` cornerstone.
> **Reference consumers:** independent projects exercise the standards in real code today — see [`docs/reference-consumers/`](../reference-consumers/) for the per-consumer shape profiles (one per known consumer, covering the desktop/Qt, Django/web, and FastAPI/SaaS shapes).
>
> **Standards stay consumer-neutral.** Per-consumer evidence — what each project does in full, organised by concern — lives in [`docs/reference-consumers/`](../reference-consumers/) and may evolve independently of the standards themselves. Closes [FEEDBACK PAPER-06](../../FEEDBACK.md) (the partial v0.18.0 fix stripped the most rot-prone line-range citations; the full restructure into `docs/reference-consumers/` shipped in v0.32.0).

---

## Why this folder exists

This folder is the **single source of truth** for the cross-cutting engineering standards used by the owner across all desktop and mobile application projects.

The standards do three things at once:

1. **Define the bar.** What "world-class" means for error handling, logging, configuration, and component design — independent of any one project.
2. **Document the reference implementation.** What `mgf.common` ships *today*, with concrete file:line citations so you can read the code, not just the description.
3. **Provide drop-in templates.** Every topic doc ships paste-able skeletons (typed, mypy-strict-clean, no surprises) that a new project can lift directly. For most components the recommended action is now "depend on `mgf-common`" rather than "copy the template" — copy is the fallback when you genuinely need a divergent shape.

If you are **starting a new desktop / mobile / CLI project**, this folder is your starting point. Read the standards, then add `mgf-common` to your dependencies. If you are **extending an existing consumer**, the standards are the bar — do not regress a feature below what they prescribe.

---

## How to navigate this folder

```
docs/standards/
├── README.md ← you are here (master index, conformance keywords, glossary)
├── DESIGN_PRINCIPLES.md ← layering, separation of concerns, replaceability, testability,
│ security/reliability/performance as first-class concerns,
│ async/concurrency rules, time + resource management
├── ERROR_HANDLING.md ← typed exception hierarchy, translation seams, top-level handlers
│ (CLI / sys.excepthook / threading / asyncio / Qt), GUI worker
│ error pipeline, crash reporter, async error paths,
│ user-facing error message style guide
├── LOGGING.md ← stdlib + JSON formatter, hierarchical logger naming, levels,
│ OpenTelemetry trace correlation, redaction, sinks (console +
│ rotating file + optional OTLP / syslog / HTTP), GUI log viewer,
│ log volume control (rate-limit / sample / dedup),
│ async-context propagation via contextvars
├── CONFIGURATION.md ← pydantic-settings, precedence (CLI > env > file > defaults),
│ schema versioning + migrations, atomic writes, lazy path
│ expansion, secrets→vault separation, discriminated unions,
│ environment-tier layering, field aliases for safe renames
├── SECURITY_STANDARD.md ← cross-project security standard: secrets management, subprocess
│ security, deserialization safety, file-system security, crypto
│ choices, network security (TLS / pinning / timeouts), input
│ validation, logging hygiene, dependency security, vulnerability
│ response, threat-model template, mechanical enforcement matrix
├── TESTING.md ← cross-project testing standard: test layout, fixture hierarchy,
│ mock-provider pattern, property tests (Hypothesis), GUI testing
│ (pytest-qt), async testing (pytest-asyncio), performance
│ benchmarks, coverage, test isolation, smoke tests, security pins
├── API_DESIGN.md ← cross-project API-design standard: __all__ discipline, semver
│ rigor, deprecation cycle, type stability + py.typed, stability
│ tiers (experimental/stable/deprecated), PUBLIC_API.md contract,
│ CHANGELOG migration recipes, backward-compat shim discipline
├── RELEASING.md ← cross-project release-engineering standard: devpi-index-
│ is-the-contract, tag discipline, version-bump flow, publish-password storage
│ (devpi_password), local-dist hygiene, recovery from a botched upload
├── PACKAGE_DISTRIBUTION.md ← where mgf-* packages live: the self-hosted devpi index
│ (magogi/prod), devpi_password publish + anonymous read, verify-devpi flow,
│ single-index consumer config, retention; PKG-01..PKG-12
│ L1-binding (pypi.org + Codeberg-registry dropped as the mgf-* channel; 3rd-party deps stay on PyPI via devpi's root/pypi base)
├── WORKFLOWS.md ← cross-project CI standard: WF-01..WF-13 rules covering
│ four-gate baseline, tag-driven publish, secret-store discipline,
│ tag-version coherence, pre-publish smoke, post-publish verify
├── WORKFLOWS_PATTERNS.md ← paste-ready Woodpecker snippets implementing every
│ WF-* rule; canonical full-pipeline recipe at the bottom
├── NAMING.md ← federation identity convention: registry/dist name = hyphens, imports = dotted
│ namespace (`mgf.<sibling>`), Codeberg slug = hyphens, local dir = hyphens
│ (SHOULD); NM-01..NM-04 L1-binding (post-2026-05-24 cutover: no
│ grandfathered slugs remain)
├── AGENTS.md ← AI-agent collaboration: AGENTS.md thin-pointer, `mgf-fed agents`
│ as the canonical briefing, signing-trailer commits (Signed-off-by +
│ Co-Authored-By), FEEDBACK paper lifecycle, memory discipline,
│ risky-action confirmation; AG-01..AG-10 L1-binding
├── TIME.md ← time discipline: UTC-at-boundary, ISO-8601 wire format,
│ monotonic clocks for durations, injectable clock for tests,
│ IANA timezone names, no `time.sleep` in async; TM-01..TM-08 L1-binding
├── PERFORMANCE.md ← perf discipline: %-regression budgets (never absolute),
│ baseline file in tree, hardware-tier tagging, pytest `perf` marker,
│ numeric failure messages, `mgf-fed bench` canonical runner;
│ PF-01..PF-08 L1-binding (closes PAPER-50)
├── OBSERVABILITY.md ← three-pillars umbrella beyond LOGGING: metric naming
│ `mgf_<domain>_<unit>_<aggregation>`, canonical label set
│ (app/version/env), OTel trace shape, SLI/SLO/alert/runbook
│ discipline; OB-01..OB-04 L1, OB-05..OB-11 (service + cross-language wire, incl. OB-10)
├── SCOPE.md ← cross-project scope policy: IN scope / OUT of scope (with cited
│ ecosystem alternatives) / Adjacent (with promotion criteria);
│ the "scope creep" review question every new-module PR must answer
├── DOCUMENTATION.md ← cross-project documentation standard: the uniform ten-doc root
│ contract + the six-bucket docs/ hierarchy + the priority-tracker
│ shape + the CLAUDE.md format + cutover guides + FEEDBACK lifecycle
│ + CHANGELOG discipline + doc:code drift detection + AI-agent
│ navigability rules
├── OPERABILITY.md ← cross-project operability standard: rich version visibility,
│ self-diagnostic `doctor`, URL resolution, headline-facts honesty,
│ config introspection, log access, diagnostic bundle, bounded state
│ growth (universal) + production safety guards, versioned rollback,
│ alerts-reach-humans, real-target restore drill (service-only)
├── DEPLOYMENT.md ← cross-project deployment standard for web-service consumer
│ applications: Infrastructure-as-Code, Configuration-as-Code,
│ immutable artefacts, secrets management, reversible deploys,
│ the `deploy/` directory shape, end-to-end observability,
│ DNS + TLS as infra, first-production-cut runbook,
│ multi-environment discipline (cloud-agnostic; Infomaniak = main platform)
├── GUI_CONSUMERS.md ← cross-project GUI-consumer standard (PySide6 / Qt): how a desktop
│                            GUI joins the federation. GUI-01..GUI-10 L1/L2 rules covering
│                            layering (Qt in presentation only), off-main-thread blocking
│                            (worker pattern), CancellationToken plumb-through, worker
│                            error pipeline, Qt-excepthook bridge, settings persistence
│                            via BaseAppSettings (not QSettings), pytest-qt + Fakes for
│                            unit tests, capability-driven UI. Reference consumers:
│                            vm-vmanager-app, hrb-app. Closes PAPER-59.
├── PRESENTATION_LAYER.md ← framework-neutral umbrella above GUI_CONSUMERS: how a domain
│                            SDK ↔ multi-UI app pair is structured (PR-01..PR-07, L1).
│                            PR-01 forbids ANY UI framework in the SDK (generalises
│                            GUI-01); PR-02..PR-05 mandate the three-layer split
│                            (core/view/ui/<framework>) when an app has 2+ UIs;
│                            PR-06 fences the SDK's stdlib-only `fmt` helpers; PR-07
│                            tracks per-rule status in conformance trackers. DRAFT
│                            pending second-adopter promotion. Reference pair:
│                            mgf-hrb (SDK side, ships `mgf.hrb.fmt` + import-linter
│                            fence) + hrb-app (app side, ships the three-layer split
│                            and absorbs both CLI + Qt GUI as sibling `ui/`s).
└── COMMON_COMPONENTS.md ← catalogue of currently-supported common components, where they
                               live in mgf.common, and how to plug them into a new project
```

---

## Suggested reading order

| If you are… | Read in this order |
|---|---|
| **Starting a new project from scratch** | `NAMING.md` Rules box (decide the four names first) → `DESIGN_PRINCIPLES.md` → `SECURITY_STANDARD.md` Rules box → `CONFIGURATION.md` → `ERROR_HANDLING.md` → `LOGGING.md` → `TIME.md` Rules box → `TESTING.md` Rules box → `API_DESIGN.md` Rules box (if publishing a library) → `COMMON_COMPONENTS.md` §"How to bootstrap". Then add `mgf-common` to your dependencies. |
| **Starting a new PySide6 / Qt GUI consumer** | `GUI_CONSUMERS.md` §"Intent" + Rules box (GUI-01..GUI-10) first — it's a one-page onboarding for the GUI-specific shape (Qt in presentation only; worker pattern; excepthook bridge; capability-driven UI). Then walk the "Starting a new project from scratch" row above. Use `mgf-fed init-project --kind service` as the scaffolder until PAPER-59 ships `--kind gui`. |
| **Designing a domain SDK that will have 2+ UI consumers (CLI + GUI + …)** | `PRESENTATION_LAYER.md` Rules box (PR-01..PR-07) — the framework-neutral umbrella. Sets up the SDK ↔ app boundary (PR-01 + PR-06), the `<sibling>-app` repo shape (PR-02), and the three-layer split inside it (PR-03..PR-05). Then specialise per-framework: GUI_CONSUMERS.md (GUI-*) for Qt; argparse / stdlib for CLI. Reference pair: `mgf-hrb` + `hrb-app`. |
| **Naming a new federation sibling** | `NAMING.md` Rules box (NM-01..NM-04) — the four-domain mapping table is the whole standard; print it. |
| **An AI agent starting work in any federation repo** | Run `mgf-fed agents` first (the canonical briefing) → `AGENTS.md` Rules box (AG-01..AG-10) — the federation's collaboration discipline → project's `docs/claude/CLAUDE.md` for project-specific lookups. |
| **Writing time-dependent code or fixing a flaky time test** | `TIME.md` Rules box (TM-01..TM-08) — UTC at boundaries, monotonic for durations, inject the clock for tests. |
| **Adding or chasing a perf regression** | `PERFORMANCE.md` Rules box (PF-01..PF-08) + §4 (failure-message shape). Relative budgets only; baselines live in `tests/perf/baselines.json` with hardware tier recorded. |
| **Wiring metrics / traces / alerts for a service** | `OBSERVABILITY.md` Rules box (OB-01..OB-11) — three-pillars umbrella; OB-01..OB-04 are L1, OB-05..OB-11 apply once you have a service to monitor. |
| **Publishing a library** | `API_DESIGN.md` Rules box + §1 mental model + §3 stability tiers + §10 CHANGELOG contract — then walk the AP-* matrix against your repo |
| **Cutting a release** | `RELEASING.md` Rules box (REL-01..REL-13) + §2 release flow — print the §2 checklist for the actual upload session |
| **Setting up CI for a new project** | `WORKFLOWS.md` Rules box (WF-01..WF-13) + `WORKFLOWS_PATTERNS.md` §8 (canonical full pipeline) — copy the recipe, parameterise, commit |
| **Extending an existing consumer** | The relevant topic doc → `COMMON_COMPONENTS.md` → the cited code in `src/mgf/common/` (or in the consumer's own `src/`) |
| **Reviewing a PR for compliance** | `DESIGN_PRINCIPLES.md` (rules) → topic docs (specifics) — every PR claim must map to a MUST/SHOULD here. The §"Self-review checklist" at the bottom of each doc is the PR author's contract. |
| **An AI agent given a vague task** | `README.md` (this file) → `DESIGN_PRINCIPLES.md` → only the topic doc the task touches. The "Rules box" at the top of each topic doc is agent-readable. The mechanical-enforcement matrix at the bottom of each doc tells the agent which rules are CI-enforceable vs review-only. |
| **Auditing security posture** | `SECURITY_STANDARD.md` Rules box + §15 mechanical-enforcement matrix → §12 threat-model template → walk the SC-01..SC-18 list against the project |
| **Setting up a new test suite** | `TESTING.md` Rules box (TS-01..TS-27) → §3 fixture patterns → §11 isolation → §10 security pins → §13 layer markers → §13.11 extended taxonomy → §19 federation supervisor. Then write the first failing test. The shortest path to a federation-conformant gate: `mgf-test-supervisor --self-check` (verifies supervisor), `mgf-test-supervisor --tier 0` (smoke), then iterate. |
| **Setting up the federation test supervisor** | `TESTING.md` §19 (TS-22..TS-27 implementation guide) → `uv add --dev "mgf-test-supervisor @ git+ssh://git@codeberg.org/magogi-admin/mgf-test-supervisor.git"` → register markers + timeout in `pyproject.toml` per §13.11 → run `mgf-test-supervisor --self-check`. The published library's README is the authoritative adoption guide; the DIAGNOSING_HANGS.md playbook at [`docs/testing/DIAGNOSING_HANGS.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/docs/testing/DIAGNOSING_HANGS.md) is your reference when a test goes red. |
| **Just looking up a fact** | Use the COMMON_COMPONENTS.md table of contents — it indexes every component by name and points at code |
| **Setting up the docs system for a new project** | `DOCUMENTATION.md` Rules box (DOC-01..DOC-12) + §2 hierarchy + §13 self-review checklist. Then ship the seven root-level docs and the six-bucket `docs/` skeleton before the first PR. |
| **Making a service / app actually runnable in production** | `OPERABILITY.md` Rules box (OP-01..OP-12) + §5 self-review checklist. The 8 universal rules (OP-01..OP-08) apply to every project with a CLI / GUI; the 4 service-only rules (OP-09..OP-12) apply when a real deployment + alerting story exists. |
| **Deploying a web service to the cloud** | `DEPLOYMENT.md` Rules box (DEP-01..DEP-11) + §3 canonical `deploy/` directory shape + §7 self-review checklist. Cloud-agnostic; §8.1 covers Infomaniak (Magogi foundation's main platform); §8.3 covers AWS / Azure / GCP shape translations; §8.4 covers managed-platform shapes (Fly.io / Render / Heroku). The reference framework is [`django-infomaniak-deploy`](https://codeberg.org/magogi-admin/django-infomaniak-deploy). |

---

## Conformance keywords

These docs use [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) keywords throughout. Every rule is tagged. Treat them as load-bearing — violations should be caught in code review.

| Keyword | Meaning |
|---|---|
| **MUST** / **MUST NOT** | Absolute requirement. A violation is a bug. Tooling (lint, mypy, tests) MUST enforce where mechanically possible. |
| **SHOULD** / **SHOULD NOT** | Strong recommendation. A deviation requires written justification in code or PR description. |
| **MAY** | Optional. Use your judgment. |

Every topic doc opens with a **Rules box** — a one-page summary of every MUST/SHOULD in that document. Skim that first; the body of the doc is rationale and templates.

---

## Conformance levels for projects

Every project that adopts the standards declares a conformance level — **L1 / L2 / L3** — in its `MGF_STANDARDS_CONFORMANCE.md`. The level measures **how strictly you follow the rules**, not which features you happen to wire:

| Level | What you commit to | Typical use |
|---|---|---|
| **L1 — Lite** | Conform to the *spirit* of the standards, on a best-effort basis. | Greenfield experiments, spikes, scratch tools. |
| **L2 — Standard** | Conform to every **MUST** rule, evidenced by a per-rule audit. | Production consumers + federation siblings — the default. |
| **L3 — Strict** | Conform to every **MUST and SHOULD** rule, with run-time enforcement (audit-logs, redaction) wired up. | The cornerstone library + high-stakes services. |

The **canonical definition lives in [`FEDERATION.md` §4](../../FEDERATION.md)** — the federation contract owns it; the table above is the summary. As the cornerstone + reference implementation, `mgf-common` itself holds to **L3**.

Declare your level in `docs/inprogress/MGF_STANDARDS_CONFORMANCE.md` (start from the [template](../recipes/mgf-standards-conformance-md-template.md)); a one-line `Conformance: L<n> per mgf-standard/docs/standards/` in your top-level README points at it. This sets the bar for code review.

**Project mode — an orthogonal axis to L1/L2/L3.** The conformance
*level* measures **how strictly** you follow the rules. It does not
capture **what kind of work this is** — and applying production-grade
guardrails to a throwaway spike produces timid, slow work with no users
to justify the caution. So there is a second, independent lens, the
**project mode**, confirmed once via the
[Agent Empowerment Charter](principles/agent-empowerment-charter.md)
mode handshake before substantial autonomous work:

| Mode | Posture |
|---|---|
| **Greenfield** | New, no users, no compatibility constraints. Propose the best design. Production guardrails ([DEP-*](DEPLOYMENT.md), [OP-09..OP-12](OPERABILITY.md), full IaC, restore drills, the LG-15 event registry) apply in **spirit**; record any deferral per [`non-adoption-is-valid`](principles/non-adoption-is-valid.md). **Do not build production ceremony for a spike.** |
| **Unconstrained brownfield** | Backward compatibility explicitly waived. Propose the design you'd build today; state migration cost honestly; breakage is a cost to weigh, not a veto. |
| **Production-constrained** | Real users / a real deployment. The production guardrails **bind** — backward compatibility, staged migration, rollback plans are requirements; prefer minimal surgical change. |

Mode and level are independent: an L2 greenfield spike and an L2
production service hold to the same MUSTs but with very different
postures toward the service-only guardrails. The service-only rules
(DEP-*, OP-09..OP-12) already carry an "applies to: service" tag; the
mode axis makes the greenfield/spike side of that explicit.

**Documented non-adoption preserves conformance.** A project at any level may consciously decline a specific primitive when adopting it would conflict with a deployment-coupled, policy-specific, or framework-architectural constraint — provided the rationale is recorded (ADR, tracker entry, or `FEEDBACK.md` paper). See [`principles/non-adoption-is-valid.md`](principles/non-adoption-is-valid.md) for the named principle, the three components (conscious decline / documented rationale / feedback if generalizable), and the worked examples (LOG-01, BOOTSTRAP-01, "small consumer" scope discipline). This is the framing behind every shipped carve-out.

**Audit-time taxonomy.** When running a per-rule conformance audit, each non-✅ row resolves into one of five categories — `❌ violation`, `⚪ partial`, `🚫 declined-with-rationale`, `N/A`, or `⏳ no-surface-yet`. The three middle categories are easy to conflate; see [`principles/audit-outcomes.md`](principles/audit-outcomes.md) for the decision tree and worked examples.

**Stable rule anchors.** Every rule row in every topic doc's *Rules box* carries an HTML anchor matching the rule ID (e.g., `<a id="CF-09"></a>` immediately before `**CF-09**`). PR comments and audit ledgers can cite a rule by URL — `https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/CONFIGURATION.md#CF-09` jumps directly to the CF-09 row. The convention closes [`FEEDBACK.md`](../../FEEDBACK.md) PAPER-48's "no citeable URL" gap; a richer mkdocs/sphinx render is post-v1.0 work.

**Per-kind subtrees.** For consumers building **web applications and APIs** (Django / FastAPI / Flask / Pyramid), see [`web/README.md`](web/README.md) — the web-domain narrative wrapper that says "for a web consumer, here's how the canonical rules land + which carve-outs apply." The canonical topic docs remain authoritative; the subtree is the discoverable front door for web-shaped consumers.

---

## The component catalogue (one-line summary)

The full list lives in [`COMMON_COMPONENTS.md`](COMMON_COMPONENTS.md). The TL;DR:

| Component | Status in `mgf.common` today | Where it lives | Standard doc |
|---|---|---|---|
| **Exception hierarchy + base class** | ✅ Strong (L1) | `src/mgf/common/exceptions/` (`AppError` base + 7 categories + 7 generic concretes) | [`ERROR_HANDLING.md`](ERROR_HANDLING.md) |
| **Typed application config** | ✅ Strong (L1) | `src/mgf/common/config/` (`BaseAppSettings` + `make_settings_config` + `load_settings`) | [`CONFIGURATION.md`](CONFIGURATION.md) |
| **Logging** | ✅ Strong (L1) | `src/mgf/common/observability/logging_setup.py` + `json_formatter.py` + `text_formatter.py` | [`LOGGING.md`](LOGGING.md) |
| **GUI worker pattern** | 🟡 Documented; concrete code is per-consumer | per-project template | [`DESIGN_PRINCIPLES.md`](DESIGN_PRINCIPLES.md) §"GUI threading" |
| **Provider abstraction (replaceability)** | 🟡 Documented; per-project ABCs in consumers | per-project template | [`DESIGN_PRINCIPLES.md`](DESIGN_PRINCIPLES.md) §"Replaceability" |
| **Crash reporter (local + remote)** | ✅ Strong (L1; remote sinks via `[observability]` extra) | `src/mgf/common/observability/crash_reporter.py` | [`ERROR_HANDLING.md`](ERROR_HANDLING.md) §"Crash reporter" |
| **Excepthooks (sys + threading)** | ✅ Strong (L1) | `src/mgf/common/observability/excepthook.py` + `threading_excepthook.py` | [`ERROR_HANDLING.md`](ERROR_HANDLING.md) §"Top-level handlers" |
| **OpenTelemetry tracing** | ✅ Strong (L2 via `[observability]` extra) | `src/mgf/common/observability/otel_setup.py` | [`LOGGING.md`](LOGGING.md) §"Correlation" |
| **Sensitive-field redaction** | ✅ Strong (L1) | `src/mgf/common/observability/redaction.py` (Bearer/JWT/PEM + named-key policy) | [`LOGGING.md`](LOGGING.md) §"Redaction" |
| **Log viewer dialog (GUI)** | 🟡 Documented; concrete code is per-consumer | per-project template (`LOGGING.md` §9.1) | [`LOGGING.md`](LOGGING.md) §"GUI log viewer" |

Each topic doc ends with a **"How to consume from your project"** section — the concrete `mgf.common.*` symbols to import and the entry-point wiring required (e.g., `mgf.common.bootstrap(app_name=...)`).

---

## How AI agents should use this folder

> **Read the canonical briefing first.** If you are an AI agent in
> any Magogi project, run **`mgf-fed agents`** — the single
> front-door briefing (same text in
> [`STARTHERE.md` §"For the AI agent"](../../STARTHERE.md)) — then
> use this folder as the rule reference.

> **You are empowered, not just bound.** This corpus is MUST-heavy so
> consistency is cheap — but it does **not** ask for blind compliance.
> Read the [**Agent Empowerment Charter**](principles/agent-empowerment-charter.md)
> ([AG-15](AGENTS.md#AG-15)): your explicit license to **push back**,
> **propose** a better path, **refine** scope (the mode handshake),
> **ask** a clarifying question, **decline with rationale**, and
> conclude **"no change needed."** Exercising judgment *with a recorded
> rationale* is conformant; silent non-compliance is not.

If you are an AI coding agent:

1. **Before writing or editing code in any of these areas** — error handling, logging, config, threading/worker — read the corresponding topic doc.
2. **The Rules box at the top of each doc is your contract.** Every MUST is non-negotiable.
3. **Templates are paste-able.** When asked to "add logging" or "add a config field," you SHOULD lift the template and adapt it, not invent a new shape.
4. **When the task hints at a gap** ("add crash reporting", "make logs work with Loki", "wire tracing"), depend on `mgf-common`'s shipped implementation rather than inventing a new shape. The reference implementation paths live in `COMMON_COMPONENTS.md` (catalogue) and the per-topic doc's "AS-IS in mgf-common" section.
5. **If a new pattern emerges** that the standard doesn't cover — or a rule looks wrong or misapplied *here* — propose an addition or push back *before* applying it, via the channels in the [Agent Empowerment Charter](principles/agent-empowerment-charter.md) (a FEEDBACK paper, an ADR, or a `🚫` decline-with-rationale). Standards diverge fast if every project invents its own conventions; they ossify if no one is licensed to question them. Both failure modes are real — the charter is how you avoid each.
6. **A consumer project's `docs/claude/CLAUDE.md`** is the *project-specific* lookup (what's been built, what's broken, gotchas). The `mgf-standard/docs/standards/` folder is the *cross-project* standard. They complement each other.

---

## How humans should use this folder

For new projects:
1. Add `mgf-common` to your dependencies. The full L1 surface (exception base, config loader, logging stack, crash reporter, excepthooks) lands in one import.
2. Add `mgf-common[observability]` if you want L2 (OpenTelemetry traces + Sentry-style remote crash sink).
3. Call `mgf.common.bootstrap(app_name=..., app_version=...)` once in every entry point — wires identity + logging + OTel + excepthooks in a single transactional call.
4. Subclass `mgf.common.exceptions.AppError` for your project's domain exceptions, and `mgf.common.config.BaseAppSettings` (via `settings_config(env_prefix="YOURAPP_")`) for your typed config.
5. Write your first feature *only* after the bootstrap files are in place.
6. Declare your conformance level in your README (e.g., `"Conformance: L1 per mgf-standard/docs/standards/"`).

For an existing consumer:
1. Use the standards as the bar for every PR. When a PR touches one of the catalogued components, the relevant topic doc's MUSTs apply.
2. Track gap-closure work as roadmap items, not ad-hoc commits — each gap is a discrete, reviewable change.
3. When `mgf-common` adds a new component or relaxes/tightens a rule, bump the consumer's `mgf-common` pin in the same PR that updates the consuming code.

---

## Versioning

The standards version (top of this file) bumps when:

- **MAJOR** — A MUST is added, removed, or relaxed (existing code in any project may be non-compliant).
- **MINOR** — A SHOULD or template changes (existing code stays compliant; new code SHOULD adopt).
- **PATCH** — Wording, examples, or AS-IS code references updated.

Each topic doc carries its own version line in its header. The master `README.md` version is the maximum of all topic doc versions.

---

## Glossary

| Term | Definition |
|---|---|
| **Cornerstone (this project)** | The reference implementation pattern — `mgf-common` is the cornerstone library; consumer projects depend on `mgf-common` and inherit the standards. |
| **Lingua franca** | A small set of frozen domain types (e.g., `VMHandle`) passed between modules so APIs are not stringly-typed. See `DESIGN_PRINCIPLES.md`. |
| **Provider / driver / adapter** | An abstract base class isolating a third-party dependency (libvirt, a database, a cloud SDK) so the rest of the codebase is testable and replaceable. |
| **Translation seam** | The single place where a third-party exception is converted to a typed application exception. See `ERROR_HANDLING.md`. |
| **Top-level handler** | The outermost catch in each entry point (CLI `main`, `sys.excepthook`, `threading.excepthook`, asyncio loop handler, Qt event loop) that converts an unhandled exception into a clean exit / dialog / log entry. |
| **Correlation ID / trace ID** | An identifier propagated across log records so a single user action can be reconstructed end-to-end. In Tier C, this is the OpenTelemetry trace ID. |
| **Sink** | A destination a log record is written to (console, rotating file, OTLP exporter, syslog, etc.). |
| **Lift-and-shift** | Copying a template from a standard into a new project verbatim or with mechanical edits (rename the package, swap the brand). With `mgf-common`, lift-and-shift is the FALLBACK — preferred path is "depend on `mgf-common`". |
| **Gap-closure** | A planned, file-specific change list to bring a consumer project from its current state to the L2 standard. Lives at the bottom of each topic doc when relevant. |

---

## Index of MUSTs

A flat, sortable list of every absolute requirement across the standards. Use this as a code-review checklist or as input to a linter rule when you write one.

Some rules are **shape-specific** — they bind only a project kind (service / GUI / web) or a deployment shape, not every project. Those carry an `applies_to` / scope qualifier in their topic-doc Rules box (e.g. DEPLOYMENT's `(service)` rows, the GUI / PR level column) and read `N/A` in an audit when out of shape (see [DESIGN_PRINCIPLES §14.2](DESIGN_PRINCIPLES.md#142-scope-the-rule-to-the-shape-it-serves-applies-to) + [`audit-outcomes`](principles/audit-outcomes.md)). A planned `mgf-fed standards --kind=<shape>` filter (audit-outcomes PAPER-47) will emit only the rows that bind a given project kind.

> **Maintenance discipline (DOC-04 same-commit shape):** when a Rules box in any topic doc changes (new MUST added, existing MUST text revised, MUST removed), this index MUST be updated IN THE SAME COMMIT. The duplication is intentional — the topic doc's Rules box is the body's quick reference; this index is the cross-doc grep target — but the drift surface is real. Treat the index like CHANGELOG.md: same-commit update or the change is incomplete. Last refreshed in the 2026-05-15 standards audit (filled gaps for WF / REL / DOC / TS-19+ / LG-15+; fixed LG-11 promotion + LG-06 v0.18 revision + AP-12 typo); **2026-06-11 (PAPER-100): added the five previously-omitted binding families — TM (6) / PF (7) / OB (10) / NM (3) / GUI (10) — plus REL-10..13 (4): ~40 MUST-level rules, taking the index to 258 across 21 families. **2026-06-13 (FB-05 promotion):** FB-05 (cross-repo feedback relay) promoted SHOULD→MUST + indexed → **259 across 22 families** (FB joins as the feedback-discipline family, now that `mgf-fed feedback` ships the relay). **2026-06-13 (AG-17 / AG-18):** in-repo agent memory (`docs/memory/`) + standardized git configuration (canonical `.gitignore` incl. always-ignore `my_stuff/`) added as AGENTS MUSTs → **261 across 22 families**. **2026-06-14 (WF-13):** the `.woodpecker.yml` made a generated artifact (rendered from the canonical template by `mgf-fed scaffold`, generation-currency enforced by `mgf-fed drift-check`) → **262 across 22 families**. **2026-06-22 (AG-19, standards v2.25):** the runtime auto-memory store (`~/.claude/projects/<slug>/memory/`) made version-controlled + off-machine-backed (private `<project>-memory` Codeberg remote, `memory/`-scoped allowlist `.gitignore` to keep session transcripts out) → **263 across 22 families**. The generated index — `gen_rules_index.py --check`, PAPER-100's suggested shape, now shipped — is the durable enforcement: index⇎Rules-box drift is a hard CI error. **2026-06-29 (AG-20, standards v2.26):** owned-infrastructure discipline — an agent MUST NOT declare an action externally-blocked without first checking the new fleet [`MGF_INFRA.md`](../../MGF_INFRA.md) registry (the asset/access inventory + recovery playbook) and attempting the self-owned recovery path; an auth/access failure on Magogi-owned infra is a solvable sub-problem, not a terminal wall — added as an AGENTS MUST → **264 across 22 families**. **2026-07-01 (AP-16, PAPER-04):** the federation pin-window for `mgf-common` (API_DESIGN §4.4) added as a MUST — this footer missed it at the time (caught by the 2026-07 pre-lock sweep, Court F-M4) → **265 across 22 families**. The footer count is now machine-gated: `scripts/check_headline_coherence.py` (invoked by `gen_rules_index.py --check`) fails whenever this count and the generated `rules.json` disagree.**
>
> **2026-07-04 (LOCK v1):** the corpus is **LOCKED at standards v3.0.0** per [`../../LOCK.md`](../../LOCK.md) — locked surfaces, the CLARIFY / EXTEND / BREAKING amendment classes (BREAKING ≈ never), and the open-at-lock register live there. Count unchanged at the lock: **265 across 22 families**.

| ID | Source | Rule |
|---|---|---|
| DP-01 | DESIGN_PRINCIPLES | Layering MUST be enforced: UI layers MUST NOT be imported by core; core MUST NOT import third-party SDKs that have a provider in front of them. |
| DP-02 | DESIGN_PRINCIPLES | Every third-party dependency that owns I/O (DB, hypervisor, cloud, ML model, OS process) MUST sit behind an ABC with at least one production and one mock implementation. |
| DP-03 | DESIGN_PRINCIPLES | Domain types passed between modules MUST be frozen dataclasses (or pydantic models with `frozen=True`); never bare strings or dicts. |
| DP-04 | DESIGN_PRINCIPLES | Every public function MUST have a type-annotated signature. mypy --strict MUST pass on `src/`. |
| DP-05 | DESIGN_PRINCIPLES | Tests MUST mirror `src/` structure 1:1 and MUST run without any production credentials, network calls, or third-party daemons. |
| DP-06 | DESIGN_PRINCIPLES | Security, reliability, performance, and error reporting are first-class concerns; every PR description MUST address all four when touching new surface. |
| DP-07 | DESIGN_PRINCIPLES | Rich inline documentation: every public class/function MUST have a docstring explaining intent and invariants. |
| DP-08 | DESIGN_PRINCIPLES | Code SHOULD be replaceable; for each major component the doc near it MUST describe the swap recipe. |
| DP-09 | DESIGN_PRINCIPLES | Cancellation MUST be explicit. Long-running ops take an explicit `CancellationToken`-like parameter; never a thread-global. |
| DP-10 | DESIGN_PRINCIPLES | No silent fallbacks. If a fallback path exists, the active backend MUST be queryable and SHOULD be logged at startup. |
| EH-01 | ERROR_HANDLING | Every exception raised by application code MUST be a subclass of the application's base error class. |
| EH-02 | ERROR_HANDLING | Third-party exceptions MUST be translated to typed application exceptions at the boundary that owns the third-party call (provider, shell wrapper, HTTP client). |
| EH-03 | ERROR_HANDLING | When re-raising a translated exception, the original cause MUST be chained via `raise NewError(...) from original`. |
| EH-04 | ERROR_HANDLING | Every entry point MUST install a top-level handler: CLI `main`, `sys.excepthook`, `threading.excepthook`, `asyncio.get_event_loop().set_exception_handler`, and Qt's `qInstallMessageHandler` + `sys.excepthook` integration when GUI is present. |
| EH-05 | ERROR_HANDLING | Unhandled exceptions MUST produce a local crash report (JSON file under the application's state dir) AND, if remote reporting is enabled, MUST be forwarded to the configured remote sink. |
| EH-06 | ERROR_HANDLING | GUI workers MUST catch every exception (typed AND untyped), forward via signal, and never crash the worker thread silently. |
| EH-07 | ERROR_HANDLING | `except Exception:` (without re-raise or typed translation) MUST NOT appear except in: (a) cleanup paths inside `finally:` / `contextlib.suppress(...)`, (b) "best-effort observer" loops that log + continue and document the invariant. |
| EH-08 | ERROR_HANDLING | Every typed exception MUST carry machine-readable fields as constructor args (e.g., `CommandError.argv`, `SchemaValidationError.errors`), not just a formatted message string. |
| EH-09 | ERROR_HANDLING | User-facing error messages MUST end in an actionable next step where possible; the hint MUST be pinned by a substring test (see §14.7). |
| EH-10 | ERROR_HANDLING | Best-effort observer code (hook executors, scheduler tick loops, alert evaluators, libvirt event callbacks) MUST follow the never-raises invariant. |
| LG-01 | LOGGING | Every module MUST acquire its logger via `logging.getLogger(__name__)` (or the equivalent canonical name); no bare `logging.info(...)`. |
| LG-02 | LOGGING | The application MUST configure logging in exactly one place (per entry point) and MUST emit JSON when stdout is not a TTY (so log aggregators can parse it). |
| LG-03 | LOGGING | Every log record MUST carry the OpenTelemetry trace_id and span_id when a span is active (added automatically by the standard formatter). |
| LG-04 | LOGGING | Sensitive fields (passwords, tokens, private keys, session cookies) MUST be redacted by the formatter before any sink sees them. The redaction set MUST be configurable. |
| LG-05 | LOGGING | Error-level logs MUST include the exception via `LOG.exception(...)` or `exc_info=True` — never just the stringified exception in the message. |
| LG-06 | LOGGING | Logs MUST reach an aggregator the operator can search — a rotating local file (desktop / single-server), the process's stdout/stderr (cloud-native; the runtime captures), or a remote sink (OTLP / syslog / HTTP, opt-in). A "console only, no aggregation" production config is non-compliant. (Revised v0.18.0 closing FEEDBACK LOG-01.) |
| LG-07 | LOGGING | GUI applications MUST ship a log-viewer dialog that reads the rotating file sink (so users can view logs without a terminal). |
| LG-08 | LOGGING | Log messages MUST use lazy %-style formatting (`LOG.info("processing %s", x)`), NOT f-strings. |
| LG-09 | LOGGING | Structured fields MUST be passed via `extra={...}`, NOT concatenated into the message. |
| LG-10 | LOGGING | Headless services MUST configure logging at their entry point with `JournalHandler` (Linux) / equivalent OS sink in addition to the file sink. |
| LG-11 | LOGGING | Operation start/end MUST be logged with a stable `operation` name field at INFO for any function ≥100 ms OR any function that crosses a process / network / storage boundary, so flows are reconstructable from logs alone (without needing the trace backend up). Short pure-Python helpers are exempt. (Promoted SHOULD → MUST in v2.4.) |
| LG-12 | LOGGING | Log emission MUST be cheap (≤100 µs per record). Heavy formatting / IO MUST happen in the handler, not the call site. |
| CF-01 | CONFIGURATION | Application configuration MUST live in a single typed object (`pydantic-settings.BaseSettings` subclass). No module reads the config file or env vars directly. |
| CF-02 | CONFIGURATION | Precedence MUST be, top-to-bottom: CLI flags → environment variables → `.env` file → on-disk config file → typed defaults in code. |
| CF-03 | CONFIGURATION | The config schema MUST carry a version field. Loading a higher version than known MUST fail loud. Loading a lower version MUST run a migration chain. |
| CF-04 | CONFIGURATION | Writes MUST be atomic (temp file + rename) with mode 0o600. Path expansion MUST happen lazily (not at module import). |
| CF-05 | CONFIGURATION | Secrets MUST NOT live in the config file. They live in a vault (system keyring or encrypted file) accessed through a separate `Vault` interface. |
| CF-06 | CONFIGURATION | Loading an unknown key from the config file MUST raise (typo protection). Missing keys MUST fall back to typed defaults silently. |
| CF-07 | CONFIGURATION | Sub-config files (hooks, schedules, alerts, profiles, lab specs) MUST follow the same shape: typed model + atomic write + version field + unknown-key rejection. |
| CF-08 | CONFIGURATION | The `Settings` object MUST be loaded once at the entry point and passed down by constructor injection. Module-global singletons are forbidden. |
| CF-09 | CONFIGURATION | A `--config <path>` CLI flag MUST always exist. The default path MUST honour XDG / OS conventions. |
| CF-10 | CONFIGURATION | Tests MUST construct `Settings` with explicit values (no env-var leakage). |
| CF-11 | CONFIGURATION | Renaming a config field MUST NOT break existing on-disk configs — use `Field(validation_alias=AliasChoices(...))` and rewrite-on-next-save. |
| CF-12 | CONFIGURATION | Mutually-exclusive backend variants MUST be modelled as a discriminated union with a `kind` discriminator field. |
| DP-11 | DESIGN_PRINCIPLES | Async tasks MUST have an owner. Bare `asyncio.create_task(...)` without retention is a defect. |
| DP-12 | DESIGN_PRINCIPLES | Time MUST be UTC at every boundary. Naive datetimes MUST NOT cross any module boundary. Full rules: TIME.md TM-01..TM-08 (single source of truth). |
| DP-13 | DESIGN_PRINCIPLES | Every owned external resource MUST be released deterministically via context manager or `try / finally`. GC-based cleanup is a defect. |
| LG-13 | LOGGING | High-frequency log sites MUST use rate-limiting, sampling, dedup, or be re-classified as metrics. |
| LG-14 | LOGGING | Custom correlation context MUST propagate via `contextvars.ContextVar`, not thread-local storage. |
| SC-01 | SECURITY_STANDARD | Secrets MUST live in a Vault, never in config / env files / source / logs / crash reports. |
| SC-02 | SECURITY_STANDARD | Subprocess invocation MUST use `argv` lists with `shell=False`. |
| SC-03 | SECURITY_STANDARD | YAML/JSON loading from any external source MUST use `yaml.safe_load` / `json.loads`. `pickle` is forbidden for IPC / persistence / untrusted data. |
| SC-04 | SECURITY_STANDARD | Files with private data MUST be written with mode `0o600` and atomically. |
| SC-05 | SECURITY_STANDARD | Cryptographic primitives MUST come from `cryptography` (or stdlib `hashlib`/`hmac`/`secrets`). No DIY crypto. |
| SC-06 | SECURITY_STANDARD | TLS verification MUST be enabled on every outbound connection. |
| SC-07 | SECURITY_STANDARD | Every external request MUST carry a finite timeout. |
| SC-08 | SECURITY_STANDARD | Untrusted input MUST be validated at the boundary (typed, range-checked, length-bounded, allow-listed). |
| SC-09 | SECURITY_STANDARD | Sensitive fields MUST be redacted by the formatter before any log sink sees them. |
| SC-10 | SECURITY_STANDARD | Dependencies MUST be pinned via lockfile + scanned for CVEs in CI. |
| SC-11 | SECURITY_STANDARD | Tracebacks / exception messages / crash reports MUST NOT leak secret material. |
| SC-12 | SECURITY_STANDARD | A `SECURITY.md` MUST exist at the repository root with vulnerability-reporting policy. |
| SC-13 | SECURITY_STANDARD | Cryptographic keys at rest MUST be derived from a passphrase via KDF or held in the system keyring. Never embedded in source. |
| SC-14 | SECURITY_STANDARD | Authentication failures MUST NOT enumerate. Repeated failures MUST be rate-limited. |
| SC-15 | SECURITY_STANDARD | Filesystem operations MUST validate against directory traversal via `Path.resolve()` + `is_relative_to()`. |
| SC-16 | SECURITY_STANDARD | Privileged operations MUST be confined to a narrow, audited surface, documented per call site. |
| SC-17 | SECURITY_STANDARD | Security-relevant actions MUST emit an `audit=true` structured log record. |
| SC-18 | SECURITY_STANDARD | Releases MUST be reproducible from source. |
| TS-01 | TESTING | `tests/` MUST mirror `src/` 1:1. CI MUST lint that no source file lacks a mirror. |
| TS-02 | TESTING | The unit suite MUST run with no production credentials, no network, and no real third-party daemon. |
| TS-03 | TESTING | Every test MUST run in isolation. Process-global state MUST be saved + restored via fixtures. |
| TS-04 | TESTING | `filterwarnings = ["error"]` MUST be set in `pyproject.toml`. |
| TS-05 | TESTING | `--strict-markers` and `--strict-config` MUST be set. |
| TS-06 | TESTING | Coverage gate ≥80% project-wide; ≥90% on changed lines in a PR; the % is a floor, behavioral adequacy is the bar (§9.5). |
| TS-07 | TESTING | Every typed exception MUST have a unit test asserting message format + field values. |
| TS-08 | TESTING | Every translation seam MUST have tests for success + each typed translation + the catch-all. |
| TS-09 | TESTING | Every "best-effort observer" MUST have a test that injects a raising observer and asserts the loop continues. |
| TS-10 | TESTING | Every security-relevant rule MUST be pinned by a test where mechanically possible. |
| TS-11 | TESTING | GUI workers MUST have tests for the success path AND the untyped-exception path. |
| TS-12 | TESTING | Async code MUST be tested with `pytest-asyncio` (or `anyio` plugin). |
| TS-13 | TESTING | Property tests (Hypothesis) MUST cover any code that round-trips data. |
| TS-14 | TESTING | Performance budgets MUST be pinned by a benchmark that measures the production code path; the budget's shape (relative threshold, `perf`-marked, off the unit baseline) is owned by PERFORMANCE.md PF-01/PF-02. |
| TS-15 | TESTING | Smoke tests against real backends MUST be opt-in (separate marker, separate CI job) and read-only by default. |
| TS-16 | TESTING | Every test failure message MUST be self-explanatory. |
| TS-17 | TESTING | Test fixtures MUST be discoverable via the conftest hierarchy, never imported across test packages. |
| TS-18 | TESTING | Slow tests (>1 s) MUST be marked `@pytest.mark.slow` and excluded from the default `pytest` invocation. |
| EH-11 | ERROR_HANDLING | Retries MUST use exponential backoff with full jitter and a finite cap. Linear / immediate retry forbidden. |
| EH-12 | ERROR_HANDLING | Operations against external systems with multi-attempt cost MUST be idempotent. |
| EH-13 | ERROR_HANDLING | Upstream-amplifying load MUST be bounded for any external call that can worsen a struggling upstream; the circuit breaker is the canonical mechanism, but a documented retry-budget (EH-11) + call-rate bound MAY be recorded in its place. |
| AP-01 | API_DESIGN | The public API surface MUST be enumerated explicitly via `__all__` at every package and module boundary. |
| AP-02 | API_DESIGN | Every public name MUST have a docstring stating intent, invariants, and at least one usage example. |
| AP-03 | API_DESIGN | The package MUST follow Semantic Versioning. Public-API breaks happen ONLY in MAJOR (or in MINOR pre-1.0). |
| AP-04 | API_DESIGN | Deprecation cycle MUST be: announce → still works (≥1 MINOR) → removed; deprecated names emit `DeprecationWarning`. |
| AP-05 | API_DESIGN | Public function signatures MUST be stable. New parameters MUST be keyword-only with defaults. |
| AP-06 | API_DESIGN | Return types MUST NOT narrow in non-MAJOR releases. |
| AP-07 | API_DESIGN | Exceptions raised by public functions are part of the public API; MUST be documented and from the typed hierarchy. |
| AP-08 | API_DESIGN | Public modules MUST use `from __future__ import annotations`; runtime-unused imports go in `if TYPE_CHECKING:`. |
| AP-09 | API_DESIGN | A PEP 561 `py.typed` marker MUST exist for any package that ships type annotations. |
| AP-10 | API_DESIGN | A `PUBLIC_API.md` MUST list every public name with its stability tier. |
| AP-11 | API_DESIGN | Stability tiers MUST be declared per public name: `experimental` / `stable` / `deprecated`. |
| AP-12 | API_DESIGN | Breaking changes MUST be documented with the four-part migration recipe (symptom / before / after / why). |
| AP-13 | API_DESIGN | A `__version__` attribute MUST be present on every distribution package, in sync with `pyproject.toml`. |
| AP-14 | API_DESIGN | Internal modules MUST NOT be imported by consumers. Single-underscore module names are private. |
| AP-15 | API_DESIGN | Backward-compatibility shims MUST emit `DeprecationWarning` AND log at INFO once per process. |
| AP-16 | API_DESIGN | Federation siblings MUST pin `mgf-common` with the wide window `>=<floor>,<1.0` (not a single MINOR), backed by a mandatory compatibility-matrix CI + a cornerstone-release ping (§4.4). |
| SP-01 | SCOPE | The library MUST publish an explicit IN-scope list. Without it, "scope creep" arguments collapse into taste arguments. |
| SP-02 | SCOPE | The library MUST publish an explicit OUT-of-scope list with reasoning + cited ecosystem alternative per entry. |
| SP-03 | SCOPE | Every PR adding a new module or top-level function MUST justify against §1 (IN) or §3 (Adjacent). PRs whose answer is "OUT" are rejected. |
| SP-04 | SCOPE | Adjacent-scope items MUST require a documented consumer-demand signal before promotion to IN. |
| SP-05 | SCOPE | The OUT-of-scope list MUST cite the ecosystem alternative for every cut. |
| SP-06 | SCOPE | Scope policy MUST be revisited on every MAJOR release; items move between IN / Adjacent / OUT as the ecosystem and consumer demand shift. |
| LG-15 | LOGGING | Every INFO+ record at a notable lifecycle / security / boundary event MUST carry a stable `event` field in `<subject>.<action>` form (e.g. `vault.read`, `bootstrap.replace`). Event names are public-API-stable; document in `docs/reference/EVENTS.md`; rename only via deprecation cycle. See LOGGING §4.5. |
| LG-16 | LOGGING | Every WARNING and ERROR record MUST answer three questions: WHAT (past-tense declarative message), WHY (structured `extra={}` fields, never concatenated), HOW (actionable hint when remediation is known — message-suffix or `hint` field). See LOGGING §4.6. |
| LG-17 | LOGGING | Every ERROR record SHOULD carry a stable `fingerprint` field so observability tools group occurrences of the same logical failure. Default: exception type FQN (formatter-computed). Override via `fingerprint` extra when args are part of identity. See LOGGING §4.7. |
| TS-19 | TESTING | Test layer markers MUST be registered in `pyproject.toml` under `[tool.pytest.ini_options].markers`. Combined with `--strict-markers`, prevents silent typos. Canonical four: `smoke` / `e2e` / `integration` / `slow`. |
| TS-20 | TESTING | Tests MUST be partitioned across four canonical directories: `tests/unit/` (default), `tests/integration/`, `tests/e2e/`, `tests/smoke/`. Each non-unit directory's tests SHOULD apply the matching marker via top-level `pytestmark`. |
| TS-21 | TESTING | Every published library MUST have a smoke layer (`tests/smoke/`) running in <100 ms total: package imports, every `__all__` name reachable, shortest happy path of every public entry function works. |
| TS-22 | TESTING | Tiered runs MUST be supported — every test assignable to tier-0..3; the runner accepts `--tier N`, `--tier N-M`, `--budget T`. |
| TS-23 | TESTING | Every CI run MUST capture a pytest crash / hang / signal-death as a structured per-test outcome (bounded hang + thread dump; single-file failure context; no bootstrap circularity). Canonical reference: a stdlib-only supervisor running pytest as a subprocess (`mgf-test-supervisor`); an equivalent mechanism meeting these outcomes is conformant (record it). Plain `pytest` from CI with no crash/hang capture is non-compliant. |
| TS-24 | TESTING | Per-test records MUST be structured — one JSON object per line in `.gates/last-run/run.jsonl` (`TestRecord`; `schema_version` mandatory). |
| TS-25 | TESTING | Flaky tests MUST be auto-quarantined — fail ≥3 of last 5 → skipped; 3 passes under `--quarantine-attempt` → evicted. (L2) |
| TS-26 | TESTING | Built-binary dependencies MUST have a freshness check — binary mtime ≥ source; stale → FAIL, missing → SKIP. |
| TS-27 | TESTING | Failures MUST be explorable from a single per-failure detail bundle at `.gates/last-run/failures/<id>.txt`. |
| TS-28 | TESTING | Per-test perf attribution MUST be opt-in, surfaced through the supervisor, and fail-open (cProfile + `perf_span`; no baseline pollution). (L2) |
| WF-01 | WORKFLOWS | Every project MUST have CI that runs on every push to a long-lived branch and every pull request. No "ship from local laptop" paths. |
| WF-02 | WORKFLOWS | The four green gates (lint / typecheck / test / import-linter) MUST be CI-enforced and MUST block merge on red. |
| WF-03 | WORKFLOWS | A library that publishes to the devpi index MUST have a tag-driven publish workflow. Pushing `v<X.Y.Z>` is the trigger; non-tag pushes MUST NOT publish. (Endpoint + auth: PACKAGE_DISTRIBUTION.md / PKG-*.) |
| WF-04 | WORKFLOWS | Publish credentials MUST be stored in the CI platform's secret store, scoped per-project, and (where supported) restricted to tag-event runs only. |
| WF-05 | WORKFLOWS | The publish workflow MUST verify tag-version coherence before uploading. Tag name MUST match `pyproject.toml::version` AND `__version__`; mismatch aborts. |
| WF-06 | WORKFLOWS | The wheel uploaded to the devpi index MUST be the one built in the CI run that's about to publish. Never re-use a wheel built earlier. |
| WF-07 | WORKFLOWS | Pre-publish smoke MUST install the freshly-built wheel into an ephemeral venv and import the top-level package + `__version__`. |
| WF-08 | WORKFLOWS | Post-publish verification MUST confirm the artifact appeared on the devpi index (the `+simple/<name>/` listing) with the expected version within a polling window — never pypi.org for an mgf-* package (PKG-05). |
| WF-09 | WORKFLOWS | Workflow files MUST pin every external dependency to a specific version (interpreter image, plugin actions, base images by digest where supported). |
| WF-10 | WORKFLOWS | Independent CI steps MUST run in parallel. Sequential ordering is reserved for genuine dependencies; matrix axes MUST fan out. |
| WF-11 | WORKFLOWS | A CI run MUST be reproducible from its inputs alone. No env vars outside what the workflow declares; no host state; no implicit network beyond pinned. |
| WF-12 | WORKFLOWS | Every CI step MUST surface its exit code, the exact command that ran, and enough log context on failure. Silent failures / `\|\| true` swallowing are forbidden. |
| WF-13 | WORKFLOWS | The `.woodpecker.yml` MUST be a generated artifact, rendered from the canonical template by `mgf-fed scaffold` — never hand-edited. `mgf-fed drift-check` enforces generation-currency; bespoke pipelines (`policy.toml [exempt].woodpecker`) fall back to the step-name check. |
| REL-01 | RELEASING | Every release MUST have a corresponding annotated git tag `v<version>` on the exact commit that built the published wheel. |
| REL-02 | RELEASING | A version string MUST NOT be reused across different wheel contents. Once `0.X.Y` is published, the local `dist/` artifact for that version is read-only. |
| REL-03 | RELEASING | `PUBLIC_API.md` and `PUBLIC_API.json` reflect master HEAD, not the published surface. They MAY be ahead of the published registry during a release window. |
| REL-04 | RELEASING | The publish password MUST NOT be passed via chat, shell history, or env vars in unmanaged sessions. Local: a `chmod 600` file / `~/.pypirc`. CI: the tag-scoped `devpi_password` org secret (devpi has no Trusted Publisher / OIDC). Install is anonymous. See PKG-03. |
| REL-05 | RELEASING | A published version is immutable — the devpi prod stage is non-volatile (a name+version is one-shot). Recovery is a recorded host-admin op (PKG-07), never a silent content swap. Bug fixes ship as new releases. |
| REL-06 | RELEASING | The release flow is strictly ordered (per PKG-04: bump → regen PUBLIC_API.json → build → tests green → twine check → upload to devpi → verify-devpi → commit → tag → push; or tag-driven via CI, PKG-09). Do not invert. |
| REL-07 | RELEASING | A release commit MUST close every FEEDBACK entry it ships: flip status to `✅ SHIPPED` with a one-paragraph retrospective. |
| REL-08 | RELEASING | Pre-release smoke MUST exercise the actually-built wheel: `pip install dist/<package>-<version>-*.whl` into an ephemeral venv + import every public top-level name. |
| REL-09 | RELEASING | Every FEEDBACK entry flipped to `✅ SHIPPED` / `DEFERRED` / `WONTFIX` MUST produce a consumer-facing notification message (CHANGELOG migration content as source). |
| PKG-01 | PACKAGE_DISTRIBUTION | Every `mgf-*` package MUST be published to + resolved from the self-hosted devpi index (`magogi/prod`); `pypi.org` and the Codeberg registry MUST NOT be `mgf-*` publish/distribution targets (third-party deps still resolve from public PyPI, via devpi's `root/pypi` base). |
| PKG-02 | PACKAGE_DISTRIBUTION | The canonical endpoints are the only ones used: upload `https://195.15.203.250.sslip.io/magogi/prod/`, index `…/magogi/prod/+simple/`, verify the version in `…/+simple/<name>/`. |
| PKG-03 | PACKAGE_DISTRIBUTION | Publish auth is the `magogi` account password (`devpi_password` in CI), stored per REL-04 discipline; install/read is anonymous. No OIDC / Trusted Publisher exists on devpi. |
| PKG-04 | PACKAGE_DISTRIBUTION | The publish flow is strictly ordered: gates → build → `twine check` → upload to devpi → verify-devpi → tag → push; the uploaded artifact MUST be the exact one built + checked in this run. |
| PKG-05 | PACKAGE_DISTRIBUTION | Post-publish verification MUST query the devpi index (the `+simple/<name>/` listing), never `pypi.org` or Codeberg for an `mgf-*` package; a local `dist/` wheel is never proof of publication. |
| PKG-06 | PACKAGE_DISTRIBUTION | Consumers MUST resolve `mgf-*` from the single devpi `--index-url` (`…/magogi/prod/+simple/`), which serves `mgf-*` + third-party (via `root/pypi`); do NOT add a bare `pypi.org --extra-index-url` (dependency-confusion surface). |
| PKG-07 | PACKAGE_DISTRIBUTION | A published version is immutable — the devpi prod stage is non-volatile (a `name+version` is one-shot). Recovery is a recorded host-admin op (`devpi remove`), never a silent swap of a version consumers may hold. |
| PKG-08 | PACKAGE_DISTRIBUTION | A retention policy is mandatory (package storage is the self-hosted devpi host's disk): keep ≥ current + previous minor; prune older versions (`devpi remove`); grow the host volume before it bites. |
| PKG-09 | PACKAGE_DISTRIBUTION | CI publishing MUST be tag-driven, build-in-CI, and authenticated by the tag-scoped `devpi_password` org secret; no publish on non-tag events; no secret echoed. |
| PKG-10 | PACKAGE_DISTRIBUTION | Naming defers to NM-01..04 (hyphenated dist names, dotted imports); the canonical "where to find it" URL for an `mgf-*` package is its devpi page `…/magogi/prod/<name>`, not `pypi.org/project/<name>`. |
| PKG-11 | PACKAGE_DISTRIBUTION | Agent/federation version checks resolve a sibling's published version against the devpi index (PKG-05), not `pypi.org`, not Codeberg, and not a local `dist/` (AG-09 amendment). |
| PKG-12 | PACKAGE_DISTRIBUTION | No residual `pypi.org` or Codeberg-registry publish/distribution surface for `mgf-*`: the only allowed `pypi.org` references are third-party links + clearly-historical notes (grep-gated). |
| DOC-01 | DOCUMENTATION | Every project — cornerstone, federation sibling, AND consumer application alike — MUST ship the **uniform ten-doc root baseline** plus a `docs/` directory (see DOCUMENTATION.md §2.0.1): `README.md`, `LICENSE`, `CHANGELOG.md`, `CONTRIBUTING.md`, `SECURITY.md`, `FEEDBACK.md`, `AGENTS.md`, `STARTHERE.md`, `DEPS.md`, `FEDERATION.md`. Only `PUBLIC_API.md`/`.json` stays library-only; `FEDERATION.md` is canonical only in `mgf-standard` (pointer stub elsewhere, DOC-17). |
| DOC-02 | DOCUMENTATION | Every project MUST organise non-root docs into the six-bucket hierarchy applicable to its shape: `docs/standards/` / `reference/` / `inprogress/` / `claude/` / `cutover/` / `recipes/`. Non-cornerstone projects' `docs/standards/` MUST NOT duplicate cornerstone content (pointer-only README, or project-specific extensions). Additional buckets allowed with a one-paragraph charter. |
| DOC-03 | DOCUMENTATION | Every long-lived bucket MUST have its own `README.md` charter ("what goes here, what doesn't, when to add / remove"). |
| DOC-04 | DOCUMENTATION | Every public-API change MUST land with a `CHANGELOG.md` entry IN THE SAME COMMIT. Breaking entries MUST link the `docs/cutover/v<X.Y.Z>.md` and the FEEDBACK entry. |
| DOC-05 | DOCUMENTATION | Every breaking change MUST ship a `docs/cutover/v<X.Y.Z>.md` guide with the four mandatory sections (symbol table / codemod recipe / manual paths / FEEDBACK back-link). |
| DOC-06 | DOCUMENTATION | Living priority trackers MUST follow the standard shape (priority table → first wave → §4 work units → §5 closed items). Every work unit MUST carry verified `file:line` evidence AND a falsifiable concrete output. |
| DOC-07 | DOCUMENTATION | Every project MUST ship `docs/claude/CLAUDE.md` in dense-lookup format — facts, file:line citations, pre-approvals — NOT human prose. |
| DOC-08 | DOCUMENTATION | `PUBLIC_API.md` MUST track `__all__` (AP-10). Companion `PUBLIC_API.json` MUST be generated from `__all__` and pinned in CI. Two pins: human-doc + machine-companion drift. |
| DOC-09 | DOCUMENTATION | Docs that name code (paths, line numbers, functions, env vars) MUST be drift-detected — either a CI lint that verifies the name exists, or a doc-comment back-reference, or both. **(v2.16)** Behavioral claims in consumer-facing docs SHOULD also be verified against the code — strongest form an executable example (doctest / `smoke`-marked example) pinned at a recorded version; non-auto-checkable claims carry a `doc_claim`/`code_truth` + `verified-against:<tag>` note (state the regime: track-HEAD same-commit vs pinned-tag at review, per REL-03). Generated docs are fixed at the SOURCE (docstring/type/schema), never by hand-patching the render; carry a HAND_AUTHORED/GENERATED/HYBRID origin tag; cross-repo source fixes go via AG-13 / FEEDBACK. |
| DOC-10 | DOCUMENTATION | `FEEDBACK.md` is the consumer-facing flow; `docs/inprogress/*.md` is internal posture. No cross-contamination. |
| DOC-11 | DOCUMENTATION | `docs/inprogress/` is a workspace, not a graveyard. Completed trackers SHOULD move to `docs/archive/<year>/` within one release cycle. |
| DOC-12 | DOCUMENTATION | Docs MUST be navigable by AI agents: relative links, `file:line` citation format, hierarchical `## §N` headings, no marketing prose. |
| DOC-13 | DOCUMENTATION | `FEEDBACK.md` MUST be repo-scoped — sibling-specific issues in the sibling's FEEDBACK.md; federation-wide in mgf-common's. |
| DOC-14 | DOCUMENTATION | Every project that depends on mgf-common MUST maintain an `MGF_ADOPTION.md` adoption tracker (siblings exempt per ADP-04). |
| DOC-15 | DOCUMENTATION | Every project that adopts the standards MUST maintain an `MGF_STANDARDS_CONFORMANCE.md` conformance tracker. |
| DOC-16 | DOCUMENTATION | Every project MUST maintain a `DEPS.md` bidirectional dependency manifest at repo root (§1 depends-on + §2 depended-on-by). |
| DOC-17 | DOCUMENTATION | `FEDERATION.md` at mgf-standard root is the canonical contract; siblings + consumers MUST link, never copy. |
| DOC-18 | DOCUMENTATION | Change propagation — a change to a coupled surface MUST update its dependents: same commit for same-repo dependents; same change-wave for cross-repo dependents (one commit per repo, cross-referenced, not "done" until every repo's commit lands). Walk the §10.4 matrix. |
| DOC-19 | DOCUMENTATION | Every project MUST keep a root `LESSON_LEARNED.md` (append-only, dated lessons log); generalising lessons ALSO route to a `pending-feedback/<target>.md` paper. Presence is the bar (a seeded file is conformant). MUST since v2.21; gated by `doctor --standards` presence check (PAPER-99). |
| FB-05 | DOCUMENTATION | Cross-repo feedback flows through a tracked `pending-feedback/<target>.md` outbox, relayed into the target's `FEEDBACK.md` by the supervisor (the sole cross-repo writer) — next `PAPER-NN`, origin cross-ref, source → `relayed/`; idempotent, via PR. Un-relayed papers MUST be surfaced (`mgf-fed feedback --check`). |
| OP-01 | OPERABILITY | The app MUST report its rich version on demand — package version + git commit SHA + active environment + key deps (Python, mgf-common, framework). CLI: `--version` rich output. Service: `/version` endpoint. |
| OP-02 | OPERABILITY | Every project MUST ship a `doctor` self-diagnostic command that probes the app's OWN state (config, persistent stores, key invariants) — distinct from any host-doctor. Output is a pass/fail checklist with `file:line` pointers on failures. |
| OP-03 | OPERABILITY | Project URLs (`Homepage` / `Documentation` / `Issues` in pyproject; URLs in `--help` / CLI errors / GUI menus) MUST resolve. CI MUST verify (HTTP-HEAD lint or no-placeholder grep). |
| OP-04 | OPERABILITY | Headline facts in `README.md` / `STARTHERE.md` / front-matter MUST match reality — phase markers, test counts, source-file counts, dep version pins, ADR statuses. The mental-model anchor for newcomers + AI agents. |
| OP-05 | OPERABILITY | Active configuration MUST be inspectable from a running app, secrets redacted per LG-04. CLI: `<app> explain` (or equivalent). Service: admin `/config` endpoint OR runtime snapshot. |
| OP-06 | OPERABILITY | Recent logs MUST be accessible without source-tree knowledge — `<app> logs` CLI, GUI Help → View Logs (LG-07), or documented aggregator URL. Path-knowledge requirement is a defect. |
| OP-07 | OPERABILITY | Every project MUST ship a `bundle` / diagnostic-tarball command producing a single attachable artefact: redacted config + last N log lines + crash reports + doctor output + system info. |
| OP-08 | OPERABILITY | State directories (crash reports, logs, ephemeral caches) MUST have bounded growth — size cap, age cap, or generational rotation. Default: 100 crash reports OR 7 days; logs 10 MB × 5 generations. |
| OP-09 | OPERABILITY | (service) Production safety guards MUST refuse dev-shaped values — mock backends, debug flags, dev tokens, sample data. `validate_production()` fails fast before listening. |
| OP-10 | OPERABILITY | (service) Every deployable artefact MUST carry a stable version tag (`image: <project>:latest` forbidden). Rollback procedure documented + exercised at least once. |
| OP-11 | OPERABILITY | (service) Every alert MUST reach a human AND link to a runbook (`annotations.runbook_url`). No business-hours gates on production-critical alerts. Paging path tested with a synthetic alert before go-live. |
| OP-12 | OPERABILITY | (service) Backup + restore MUST be exercised end-to-end against the real target (S3 / R2 / GCS production credentials), not just a CI mock. Quarterly drill recorded. |
| DEP-01 | DEPLOYMENT | (service) Cloud infrastructure (VM, network, LB, bucket, security group, DNS record, certificate) MUST be Infrastructure-as-Code. Manual console clicks are a defect. |
| DEP-02 | DEPLOYMENT | (service) VM / container state MUST be Configuration-as-Code (Ansible / Chef / Salt / cloud-init / Dockerfile). No `ssh && apt install`. |
| DEP-03 | DEPLOYMENT | (service) Release artefacts MUST be immutable per release — same git SHA produces byte-identical bytes. Dependencies locked at build time; no `pip install --upgrade` at deploy time. |
| DEP-04 | DEPLOYMENT | (service) Production secrets MUST live outside the repo, encrypted at rest. Acceptable: Ansible Vault, sealed secrets, cloud KMS / Secrets Manager, HashiCorp Vault. Per SC-01. |
| DEP-05 | DEPLOYMENT | (service) Deploy / backup / restore / rollback scripts MUST take an environment argument (prod / staging / dev) and MUST refuse bare invocation. Idempotent. |
| DEP-06 | DEPLOYMENT | (service) Deploys MUST be reversible with a documented, drill-measured, bounded rollback time stated in the runbook. ≤5 min is the SHOULD-target for instant-cutover shapes; snapshot-restore MAY state a higher justified bound. Drill-tested. Per OP-10. |
| DEP-07 | DEPLOYMENT | (service) The `deploy/` directory MUST follow the canonical shape: README + IaC sub-dir + config-management sub-dir + scripts/ + monitoring/ + docs/ (with phases + runbook + SLO). See DEPLOYMENT.md §3. |
| DEP-08 | DEPLOYMENT | (service) Production MUST be observable end-to-end: metrics, logs, traces flow to a queryable sink; SLI/SLO contract committed in `deploy/docs/slo.md`; alerts route to a human + link a runbook per OP-11. |
| DEP-09 | DEPLOYMENT | (service) DNS records MUST be in IaC OR a committed external-manager record list. TLS certificates MUST auto-renew (Let's Encrypt / cloud-managed). Certificate-expiry monitoring required. |
| DEP-10 | DEPLOYMENT | (service) A `deploy/docs/first-production-cut.md` runbook MUST document the green-field provisioning sequence end-to-end. Exercised at least once before go-live. |
| DEP-11 | DEPLOYMENT | (service) Every web-service consumer MUST be deployable to ≥2 environments (prod + at minimum one of staging / dev) from the same IaC + config-management code, parameterised by an environment file. |
| PR-01 | PRESENTATION_LAYER | A domain SDK MUST NOT import any UI framework (PySide6, PyQt6, textual, rich, click, flask, fastapi, django, …). Enforced mechanically via `import-linter`. Generalises GUI-01 (which is the Qt specialisation). |
| PR-03 | PRESENTATION_LAYER | An app repo with multiple UIs MUST follow three-layer separation: `core/` (domain adapter; no UI deps), `view/` (framework-free view-models), `ui/<framework>/` (the only layer that imports the framework). |
| PR-04 | PRESENTATION_LAYER | The layer hierarchy MUST be enforced mechanically via `import-linter` (or equivalent): `core/`+`view/` forbid UI frameworks; `ui/<framework>/` forbids imports from any peer `ui/<other>/`. Runs in CI as a blocking gate. |
| PR-05 | PRESENTATION_LAYER | Each `ui/<framework>/` adapter MUST consume `view/` only — never another `ui/<other>/` adapter. UIs are siblings, not parents. Shared rendering lives in `view/` or `<sdk>.fmt` (PR-06). |
| PR-07 | PRESENTATION_LAYER | Conformance trackers MUST classify PR-* per the audit-outcomes taxonomy. A pure-SDK sibling with no UI MAY mark PR-02..PR-05 as N/A (activates at first UI). PR-01 always applies. |
| AG-01 | AGENTS | Every repo MUST ship `AGENTS.md` at root as a thin pointer to `mgf-fed agents` (federation-identical; project-specific notes go in `docs/claude/CLAUDE.md`, never in `AGENTS.md`). |
| AG-02 | AGENTS | The canonical agent briefing MUST be what `mgf-fed agents` prints — one message for the whole federation. |
| AG-03 | AGENTS | Agent-authored commits MUST carry both signing trailers — `Signed-off-by:` (human reviewer) AND `Co-Authored-By:` (model name + context size). |
| AG-04 | AGENTS | Agents MUST file reusable friction as a FEEDBACK paper (`mgf-fed feedback-howto`), into the FEEDBACK.md of the project that caused it (routing per AG-11). |
| AG-05 | AGENTS | Agents MUST verify memory claims (paths, names, versions) against current state before recommending action; stale memories are updated or deleted, not propagated. |
| AG-06 | AGENTS | Risky operations (destructive / hard-to-reverse / shared-state) MUST require explicit confirmation unless a durable instruction authorizes; authorization is scoped to the action it named. |
| AG-07 | AGENTS | Agents MUST use TaskCreate/TaskUpdate for any work spanning ≥3 steps; single-step work MUST NOT (bureaucracy theatre). |
| AG-08 | AGENTS | Memory writes MUST be federation-scoped (durable facts), not session-scoped; activity logs / conversation summaries are not memory. |
| AG-09 | AGENTS | When a recommendation depends on a sibling's published version, the agent MUST verify against the devpi index (PKG-05/PKG-11) — the `+simple/<name>/` listing — not the local `dist/` wheel. |
| AG-10 | AGENTS | Standards drift an agent *finds* MUST be filed as a PAPER, not silently fixed (neither edit-doc-to-match-code nor edit-code-to-match-doc). |
| AG-11 | AGENTS | Cross-project feedback MUST be filed in the TARGET project's FEEDBACK.md (cross-cutting → mgf-common), carrying enough to triage + act (what hurts / why / evidence / suggested shape). |
| AG-12 | AGENTS | Every project MUST expose a project-scoped briefing via `mgf-fed agents --project` (content lives in `docs/claude/CLAUDE.md`). |
| AG-13 | AGENTS | Only the mgf-common supervisor may change a library; other projects MUST NOT — they file a request in the target library's FEEDBACK.md. |
| AG-14 | AGENTS | Agents MUST propagate a change to its coupled surfaces in the SAME change (walk the DOC-18 §10.4 matrix) — same commit in-repo; same change-wave cross-repo (one commit per repo, cross-referenced, done only when every repo's commit lands); never leave a dependent stale. |
| AG-15 | AGENTS | Agents are empowered — and MUST read the [Agent Empowerment Charter](principles/agent-empowerment-charter.md) — to push back, propose, refine scope, decline-with-rationale, ask a clarifying question, and conclude "no change needed." Exercising judgment with a recorded rationale is conformant; silent non-compliance is not. |
| AG-16 | AGENTS | Every project MUST keep the standards corpus resolvable to its agents — depend on `mgf-common[standards]` (the private-index-only optional extra carrying the rules + contract + design + registry). A plain `mgf-common` install does NOT carry it; the federation CLI degrades loudly without it. |
| AG-17 | AGENTS | Every repo MUST keep in-repo agent memory at `docs/memory/` — a committed `MEMORY.md` index + one-fact-per-file topic notes (name/description/type frontmatter). Travels with the repo (survives a fresh clone; shared across agents/machines); kept current per AG-05, durable-only per AG-08. Complements `docs/claude/CLAUDE.md` (DOC-07) + `LESSON_LEARNED.md` (DOC-19). Presence is the bar; doctor-checked. MUST since v2.22. |
| AG-18 | AGENTS | Every repo MUST use the federation's standardized git config — the canonical `.gitignore` (build/test artifacts + `.idea/`/`.vscode/` + `.claude/settings.local.json` + **`my_stuff/`** for local secrets, NEVER committed) + the `.gitmessage` template wired via `commit.template` (AG-03 trailers) + the committed **`.githooks/prepare-commit-msg`** hook (`core.hooksPath`) and **`scripts/check_commit_trailers.py`** run as the generated `.woodpecker.yml`'s authoritative `commit-trailers` CI gate (AG-03). `catch-up --apply` adds missing ignore lines + distributes the hook/checker; `doctor` checks `my_stuff/` is ignored and the `prepare-commit-msg` hook is present. MUST since v2.22 (commit-trailer enforcement tightened in the PAPER-102 ship). |
| AG-19 | AGENTS | The runtime auto-memory store (`~/.claude/projects/<slug>/memory/`, the private store of AG-05/AG-08) MUST be git-tracked + pushed to a **private** Codeberg remote (`<project>-memory`) so it survives disk loss and is auditable across machines. **SAFETY:** scope git to the `memory/` dir ONLY — never the parent (session `*.jsonl` transcripts may hold secrets); allowlist `.gitignore` (`*`, `!*.md`). Does not relax AG-08/AG-05; complements AG-17 (in-repo memory travels with the code, AG-19 protects the private runtime store). Bootstrap via `scripts/init_memory_vcs.py`; not CI-enforceable (machine-local). MUST since v2.25. |
| AG-20 | AGENTS | Before declaring an action **blocked / human-gated / impossible**, an agent MUST (a) check whether the dependency is Magogi-owned via [`MGF_INFRA.md`](../../MGF_INFRA.md) and (b) for owned infra, attempt the self-owned recovery path (SSH, mint/rotate a credential, restart a service) — an auth/access failure on owned infra (expired token, 401, stopped service) is a solvable sub-problem, not a terminal wall. Reason from capabilities/assets, not stated state. When something genuinely can't proceed, state the blocking assumption explicitly. Recorded "blocked"/"gated" notes MUST carry an unblock-path + as-of date and be re-derived, not inherited. MUST since v2.26. |
| TM-01 | TIME | Every `datetime` that crosses a boundary MUST be timezone-aware and UTC. |
| TM-02 | TIME | Wire format for datetimes MUST be ISO-8601 / RFC-3339. |
| TM-03 | TIME | Duration measurements MUST use a monotonic clock. |
| TM-04 | TIME | Production code MUST NOT call `datetime.now()` directly when the call is testable. |
| TM-07 | TIME | Timezone names MUST come from the IANA database. |
| TM-08 | TIME | Sleeping / scheduling MUST use a deadline-based API when the caller is async. |
| PF-01 | PERFORMANCE | Performance budgets MUST be expressed as a regression threshold against a recorded baseline. |
| PF-02 | PERFORMANCE | Perf tests MUST be marked with `@pytest.mark.perf`. |
| PF-03 | PERFORMANCE | Every active perf budget MUST have a baseline recorded in `tests/perf/baselines.json`. |
| PF-04 | PERFORMANCE | Re-baselining MUST require human approval. |
| PF-05 | PERFORMANCE | Perf tests MUST run on a harness that enforces the warm-up phase, the minimum sample count, the statistical-summary shape, and the `baselines.json` result-format that PF-01/PF-03/PF-07 require. |
| PF-07 | PERFORMANCE | Perf-test failures MUST surface the comparison numerically. |
| PF-08 | PERFORMANCE | Hardware-tier-sensitive results MUST record the tier. |
| OB-01 | OBSERVABILITY | Observability MUST be the three-pillars shape. |
| OB-02 | OBSERVABILITY | Every metric name MUST follow the federation convention `mgf_<domain>_<unit>_<aggregation>`. |
| OB-03 | OBSERVABILITY | Every metric MUST carry the canonical label set. |
| OB-04 | OBSERVABILITY | Traces MUST be OpenTelemetry-shaped. |
| OB-05 | OBSERVABILITY | Every customer-facing operation MUST have a defined SLI. |
| OB-07 | OBSERVABILITY | Every alert MUST be actionable. |
| OB-08 | OBSERVABILITY | SLI / SLO / alert definitions MUST be versioned alongside the code they describe. |
| OB-09 | OBSERVABILITY | The structured `LogRecord` schema (`mgf.common.observability.LogRecord`) MUST evolve additively + non-breakingly. |
| OB-10 | OBSERVABILITY | Every runtime emits the `LogRecord` wire shape byte-identically, pinned against one shared golden. |
| OB-11 | OBSERVABILITY | Per-app logging statistics (`mgf.common.observability.LogStatsCollector`) MUST be cheap, bounded, and fail-safe. |
| NM-01 | NAMING | Distribution names MUST use hyphens, never underscores. |
| NM-02 | NAMING | Python imports MUST use the dotted namespace `mgf.<sibling>`. |
| NM-03 | NAMING | Codeberg repo slugs MUST use hyphens. |
| GUI-01 | GUI | Federation libraries (anything under `mgf.*` except the GUI-consumer's own `mgf.<consumer>.gui`) MUST NOT import `PySide6` / `PyQt6` at module level. |
| GUI-02 | GUI | Blocking or streaming SDK / federation-library calls MUST run off the Qt main thread, and the off-thread worker MUST satisfy the worker invariant: (a) the call runs off the Qt main thread; (b) **exactly one terminal signal fires per operation** — success, failure, or cancellation; (c) **cancellation is a distinct outcome, never reported as failure**. |
| GUI-03 | GUI | Every long-running worker operation MUST accept an explicit `CancellationToken` (per [DESIGN_PRINCIPLES.md](DESIGN_PRINCIPLES.md) DP-09). |
| GUI-04 | GUI | GUI workers MUST catch every exception (typed AND untyped), report via typed signals (`completed(result)` / `failed(exc)` / `cancelled()`), and never let an exception cross the worker-thread boundary uncaught. |
| GUI-05 | GUI | `mgf.common.bootstrap()` MUST run before any Qt import in `main()`. |
| GUI-06 | GUI | Presentation widgets (windows, dialogs, panels, models) MUST NOT contain business logic. |
| GUI-07 | GUI | Streaming SDK calls (e.g., `client.watch_vm(vm_id)`) MUST map to a streaming worker that emits one signal per yielded item, plus terminal signals (`finished()` on normal exhaustion, `failed(exc)` on error, `cancelled()` on token cancel). |
| GUI-08 | GUI | GUI-state persistence (window geometry, last-opened item, recent-history, theme preference, etc.) MUST go through a `BaseAppSettings`-derived class — NOT directly through `QSettings`. |
| GUI-09 | GUI | GUI unit tests MUST run with `pytest-qt` AND a `Fake*Backend` from the consumed federation library (e.g., `mgf.vm.core.fakes.FakeHypervisorBackend`). |
| GUI-10 | GUI | GUI features that depend on backend capabilities MUST query `.capabilities()` (or the equivalent on the consumed surface) and show / hide / disable controls accordingly. |
| REL-10 | RELEASING | A `mgf-common` minor bump that breaks any sibling's existing pin upper-bound MUST trigger a federation cohort-walk release wave. |
| REL-11 | RELEASING | Cohort-walk release waves MUST follow the Phase A / Phase B split. |
| REL-12 | RELEASING | Phase A agents MUST carry a graceful pytest-denial fallback. |
| REL-13 | RELEASING | Every release MUST pass the federation consistency gate — releasing one or more libraries means the WHOLE federation is left consistent and verified. |

> **PR-* status: DRAFT.** PR-01..PR-07 ship in [`PRESENTATION_LAYER.md`](PRESENTATION_LAYER.md) grounded in one reference pair (`mgf-hrb` + `hrb-app`). The DRAFT marker drops when a second independent sibling pair adopts the shape. Until then, the MUSTs are L1-binding for the reference pair only; other siblings adopt opportunistically. PR-02 and PR-06 are SHOULDs and not listed above.

---

## Release history

The per-version history of standards changes (what each `v2.x` bump added,
tightened, or removed) lives in the canonical [`CHANGELOG.md`](../../CHANGELOG.md) — it is no longer duplicated here, so a
standards change updates ONE history (the changelog), not two. The current
rule set is the [Index of MUSTs](#index-of-musts) above.

## Cross-references

- `mgf-common` package documentation: [`../../README.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/README.md)
- Extraction history (Round 5 archive): [`../internal/EXTRACTION_HISTORY.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/docs/design/extraction_history.md)
- Per-release notes: [`../../CHANGELOG.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/CHANGELOG.md)
- Release-engineering discipline: [`RELEASING.md`](RELEASING.md)
- Per-consumer profiles: [`docs/reference-consumers/`](../reference-consumers/)

---

*This is a living document. When a consumer surfaces a missing standard or `mgf.common` ships a new component, update the relevant topic doc and the catalogue table above.*
