# Recipe — shared code & the duplication discipline

> **What this covers:** when federation code should be *shared* vs *duplicated*, and how to keep
> "one behavior, one home" without breeding a god-library. A design-time discipline, not a gate.
> **Origin:** folded back from the **Plasma project's** (since renamed **soothfast**) "Shared Code Standard (the Commons)" via
> `mgf-standard/FEEDBACK.md` **PAPER-107** — a field-proven adopter design. Adopted as a recipe +
> the **NM-05** SHOULD (junk-drawer names); the per-rule elements are SHOULD-level judgment, not new
> MUSTs (promotable to MUSTs if/when the Index re-baseline lands — see PAPER-100).

## 0. Intent — and the counterweight

**One behavior, one home.** A federation concept (a canonical encoder, an ID scheme, a time/hashing
helper, a provider-access pattern) should be implemented **once** — in `mgf-common` or the owning
sibling — and *consumed*, not copied. Consistency comes from shared code, not from carefully
maintained duplicates that silently drift until they disagree.

The counterweight, stated up front so this discipline is never weaponised into premature
abstraction: **duplication is cheaper than the wrong abstraction.** Capturing real redundancy and
forcing a speculative one-consumer abstraction are *both* defects. Judgment over bureaucracy.

## 1. The DUP check (design-time — do this before adding a module/function)

1. **Does an existing home already own this behavior?** Check `mgf-common` (and the owning sibling)
   before reimplementing — `mgf-fed standards`, the sibling's `PUBLIC_API.md`, a grep for the
   responsibility (encoders, orderings, ID/hash schemes, provider access). If yes → consume it.
2. **Two implementations of the same behavior anywhere = a DUP defect** — consolidate, or file a
   waiver (§3). The check is meant to cost minutes; if it costs more, that's friction worth a FEEDBACK note.

## 2. When code earns a shared home — the rule of three

Extract into a shared home (`mgf-common`, or a sibling that owns the domain) when **either**:
- **two confirmed consumers** exist *today* (hypothetical future consumers do not count), **or**
- a **third occurrence** of the same logic appears.

One consumer + speculation never qualifies. Until then, leave a grep-able marker at the site —
`# SHARED-CANDIDATE(<proposed-home>): <one-line reason>` — so the moment a second real consumer
appears the extraction is pre-identified.

## 3. Duplication-as-defect + waivers

Discovered duplication of shared-concept logic is a defect — log it and consolidate. A **waiver**
(duplication knowingly kept) is allowed when consolidation would force a wrong abstraction or couple
unrelated subsystems; it carries a one-line reason in the PR/CHANGELOG. Incidental small duplication
(a few lines, no shared semantics) needs no waiver.

## 4. Naming — no junk drawers (NM-05)

Shared modules are named for a **domain** (`encoding`, `hashing`, `time`, `ids`). The names
`utils`, `misc`, `helpers`, `common`, `core`-as-grab-bag and equivalents are banned — a junk drawer is
how a commons dies (nothing has a home, everything accretes). See **NAMING.md NM-05**.

## 5. Blast-radius tier on shared code

Shared code = shared blast radius. Classify each shared module:
- **Contract tier** — its output bytes reach a wire/transcript/hash/ID consumers depend on
  (canonical encoders, ID/hash schemes, orderings). A change is contract-breaking by definition →
  follows AP-03 (SemVer / MAJOR) + OB-10 (one-wire-one-golden, byte-for-byte) + a reviewed re-bless.
- **Internal tier** — everything else; normal review + the owning package's gates.

## 6. Eviction is first-class and blame-free

If a shared module's consumers drop to ≤1, or the abstraction is fighting its consumers → **inline it
back.** Reversing a wrong abstraction is a *success* of this discipline, not a failure of its author.
Keep both the shared module and each consumer behavior-tested so inlining never reduces coverage.

## Failure modes this prevents

god-library (speculative abstraction, blocked by §2) · wrong-abstraction lock-in (blocked by §6
cheap eviction) · the junk drawer (blocked by §4 / NM-05) · **silent divergence** — two copies of one
behavior drifting until they disagree (blocked by §1 + the DUP-defect class) · blast-radius surprise
(blocked by §5).

## Cross-references

DP-08 (replaceability) · NM-05 (junk-drawer names) · AP-03 (SemVer on contract-tier changes) ·
OB-10 (cross-language wire goldens) · SP-04 (Adjacent-scope promotion = the rule of three for a library's surface).
