ResolutionReport
The result of a resolution: a {@see ResolutionStatus} plus the learnable `errors` attached to the blocking entries, what `resolved`, the `loadOrder` the graph dictates for booting, what is `missing`, the `conflicts` and non-blocking `warnings`, the `legacy` dependencies in use, `migrationHints`, `learnLinks` into the Academy, and free-form `metadata`. Designed to be read by a human on the CLI, by CI, by an agent, and by the Academy alike, so {@see toArray()} serializes with a fixed, deterministic key order — the same report renders byte-for-byte identically every time. `errors[]` leads (right after `status`) so an agent reads the diagnosis first (spec §20). `loadOrder[]` is the one list whose ORDER is the payload: each entry is a `{name, version}` package identity, sequenced by the engine's topological pass — it is never re-sorted.
ResolutionReport::__construct()
public function __construct(Milpa\Resolver\Report\ResolutionStatus $status, array $resolved = [], array $loadOrder = [], array $missing = [], array $conflicts = [], array $warnings = [], array $legacy = [], array $migrationHints = [], array $learnLinks = [], array $metadata = [], array $errors = []):Parameters
| Name | Type | Description |
|---|---|---|
| $status | Milpa\Resolver\Report\ResolutionStatus | |
| $resolved | list<array<string, mixed>> | |
| $loadOrder | list<array<string, mixed>> | |
| $missing | list<array<string, mixed>> | |
| $conflicts | list<array<string, mixed>> | |
| $warnings | list<array<string, mixed>> | |
| $legacy | list<array<string, mixed>> | |
| $migrationHints | list<array<string, mixed>> | |
| $learnLinks | list<array<string, mixed>> | |
| $metadata | array<string, mixed> | |
| $errors | list<LearnableArchitectureError> |
ResolutionReport::fromArray()
public static function fromArray(array $data): selfRehydrate a report from its serialized array form. Round-trip contract (frozen in ReportShapeContractsTest): `toArray(fromArray(toArray($r)))` is byte-identical to `toArray($r)` for every engine-emitted report. At the malformed boundary it is DEFENSIVE by design — a non-record entry inside a list is dropped and a non-map `metadata` collapses to `[]`, so rehydration never propagates a shape the engine could not have emitted — and each error's `recommendedActions` is derived state, re-computed from its code + context rather than read back.
Parameters
| Name | Type | Description |
|---|---|---|
| $data | array<string, mixed> |
Throws
InvalidManifestException When `status` is absent or is not a known status.
ResolutionReport::firstLearnableLine()
public function firstLearnableLine(): ?stringThe canonical one-line teaching message of the report's FIRST learnable error, or `null` when `errors[]` is empty: `{code}: {message} — {why} Fix: {fixes[0]} Learn: {learn.academy.en}`. This is THE line a blocked boot logs or throws — the exact composition the runtime kernel and the host's Plugins loader each duplicated by hand until Orden T2; both now delegate here, so the message can never drift between surfaces. Defensive by contract: an error with no fixes or no English academy link still composes, with the segment left empty.
ResolutionReport::toArray()
public function toArray(): arraySerialize to an array with a fixed, deterministic key order; `status` becomes its string value and each attached error is expanded to its agent shape (spec §20).