Skip to content
docsv0.7.1

ErrorCatalog

The single source of learnable-error content (spec §13/§19). For each error code it holds the cause (`why`), a message template, human `fixes`, and the LIVE, bilingual Academy `links` — and builds a {@see LearnableArchitectureError} from a code plus the entry context. The catalog enforces spec §25 anti-pattern 4 ("error muerto"): every code carries why + fix + Academy link, proven by walking the whole catalog in the test suite. Links are the URLs verified live in production — never invented; since the superficies wave EVERY code points at the lesson that actually teaches it (version-contrato, legacy-y-migracion, superficies-puertas, riesgos-aceptados, skeleton-boot, contratos-grafo, atlas-limites) — no code rides the Academy root anymore. It covers the 11 initial codes of spec §13, the two codes that split the engine's ambiguous usages (`MILPA_SURFACE_NOT_ENABLED`, `MILPA_SUGGESTED_CAPABILITY_MISSING`), `MILPA_RISK_EXPIRY_UNEVALUATED` (an accepted risk whose expiry could not be checked because the caller supplied no clock), `MILPA_LEGACY_NOT_ALLOWED` (a legacy-shaped resolution the host profile's allowlist does not permit — the enforcement of `allowedLegacyContracts`), `MILPA_DEPENDENCY_CYCLE` (packages that require each other in a cycle, for which no boot order exists), `MILPA_MANIFEST_DRIFT` (a `milpa.json` that no longer matches the code's `#[PluginMetadata]` — caller-emitted by {@see \Milpa\Resolver\Ingest\DriftDetector::toLearnableErrors()}, never by the engine), and `MILPA_CAPABILITY_VERSION_UNSUPPORTED` (a capability whose providers exist but none satisfies the consumer's constraint — split from the CONTRACT version code so each side teaches its own upgrade path). Messages attribute their requirer: when `context.requiredBy` names a package or a contract, the templated message names it too, so the reader learns WHO opened the graph — not just what is missing. Host-origin entries (a `hostProfile:`-prefixed requiredBy) keep the host phrasing. The attribution covers the missing codes AND both version codes (`MILPA_CONTRACT_VERSION_UNSUPPORTED` / `MILPA_CAPABILITY_VERSION_UNSUPPORTED` — a consistent pair, per the Orden-slice precedent). Three context fields refine a message further: `oneOf` (a missed capability requirement's exhausted alternatives) makes the capability-missing message enumerate every candidate tried, `providedBy` on a capability version miss names WHICH oneOf candidates exist only out of range (so the message never claims the primary id "is provided" when only an alternative is), and `fallback` (a suggestion record's declared degradation path) makes the suggested-capability message name where the runtime degrades to.

ErrorCatalog::codes()

public static function codes(): array

Every code the catalog knows, in a stable order.

ErrorCatalog::has()

public static function has(string $code): bool

Whether a code has a catalog entry (used to decide which report entries earn a learnable error).

Parameters

Parameters of has()
NameTypeDescription
$codestring

ErrorCatalog::for()

public static function for(string $code, array $context = []): Milpa\Resolver\Report\LearnableArchitectureError

Build the learnable error for a code, templating its message and fixes with the entry context.

Parameters

Parameters of for()
NameTypeDescription
$codestring
$contextarray<string, mixed>

Throws

\InvalidArgumentException When the code has no catalog entry.