Skip to content
docsv0.9.1

Kernel

The fresh, bootable Milpa kernel: COMPOSES the published family instead of reimplementing it. `boot()` wires, in order: a DI container ({@see \Milpa\Container\DIContainer}) -> an event dispatcher ({@see \Milpa\Eventing\EventDispatcher}) -> an architecture resolution through `milpa/resolver`'s {@see GraphResolver} (fails BEFORE any plugin boots, with a learnable message — this replaces the retired {@see \Milpa\Services\CapabilityGraphChecker}, spec §24.7) -> plugins loaded and booted in `provides`-\>`requires` order (the `loadOrder[]` the resolver's own {@see ResolutionReport} dictates — one topological pass, no second sort) -> route table assembly over `milpa/http`. Every step emits the same lifecycle events the legacy host kernel's event-driven retrofit introduced (`plugin.booting`/`plugin.booted`, `capability.resolved`, `kernel.booted` — see {@see \Milpa\Events}), plus the new `architecture.resolved` carrying the resolver's full report. Zero Doctrine, zero legacy `Milpa\Web`: the active-plugins list is whatever `list<class-string>` the caller passes via `$config['plugins']` — a config array, a file `require`d into that array, or filesystem discovery the caller performs before calling `boot()`. This class never queries a database to decide what to boot; a persistence-backed plugin registry is something a *plugin* can add later, never something the kernel requires.

Kernel::boot()

public static function boot(array $config = []): self

Boots the kernel: builds (or accepts injected) collaborators, resolves the host root, resolves the whole architecture graph through `milpa/resolver` (blocking a bad graph BEFORE any plugin boots), orders the configured plugins, boots each in order while emitting the lifecycle events, and assembles the route table from every booted `RouteProviderInterface` plugin.

Parameters

Parameters of boot()
NameTypeDescription
$configarray{root?: (string | null), name?: string, plugins?: list<class-string>, config?: array<string, mixed>, hostProfile?: array<string, mixed>, evaluatedAt?: string, container?: DIContainerInterface, dispatcher?: MilpaEventDispatcherInterface, logger?: LoggerInterface, toolRegistry?: (ToolRegistryInterface | null), pluginBoot?: Boot\PluginBootStrategyInterface}Every key is optional: `root` defaults to {@see RootResolver}'s auto-detection, `plugins` defaults to an empty list, `config` is the app-config bag plugins read via `$container->get(Config::class)` (the seam that replaces plugin constructor args and env-var globals), `container`/`dispatcher`/`logger` default to fresh family instances (injecting your own is the seam tests use to observe lifecycle events before `boot()` runs), `toolRegistry` defaults to null — wiring one is the host's opt-in, `milpa/runtime` never constructs one itself. `hostProfile` (a {@see HostProfile::fromArray()} shape) is the architectural profile the resolver checks against; ABSENT it defaults to a DELIBERATELY PERMISSIVE profile — name `$config['name']` or `'host'`, version `0.0.0`, `allowedLegacyContracts: ['*']`, NO `requiredCapabilities` — so a graph that boots today (plugin `requires` all satisfied by some plugin's `provides`) resolves identically and BC holds. `evaluatedAt` (an ISO-8601 datetime) is passed straight through to the resolver as the clock for accepted-risk expiry; the resolver, not the runtime, validates it. A blocked graph throws {@see ArchitectureBlockedException} — a {@see PluginDependencyException} subclass, so every catch that worked against the retired {@see \Milpa\Services\CapabilityGraphChecker} still works (narrowing BC) — with the report's own learnable first line as the message (code + why + first fix + Academy link) and the whole {@see ResolutionReport} riding on `->report`. Boot listeners still get the report on the `architecture.resolved` event when the graph is NOT blocked.

Throws

AttributeNotFoundException A configured plugin class carries no `#[PluginMetadata]`.

ArchitectureBlockedException The architecture graph is `blocked` (an unmet required contract/capability, a conflict — a dependency cycle included — or an un-permitted legacy path); carries the full report.

\Milpa\Resolver\Exceptions\InvalidManifestException The `hostProfile` array or the `evaluatedAt` clock is malformed, or a plugin's `PluginMetadata` version is not a parseable version string (all validated by the resolver, not the runtime).

\Milpa\Runtime\Support\RootNotFoundException The host root could not be resolved and none was given explicitly.

Kernel::container()

public function container(): Milpa\Interfaces\Di\DIContainerInterface

The DI container every plugin and controller was resolved through.

Kernel::dispatcher()

public function dispatcher(): Milpa\Interfaces\Event\MilpaEventDispatcherInterface

The event dispatcher every lifecycle event was emitted on.

Kernel::router()

public function router(): Milpa\Http\Routing\Router

The route table assembled from every booted `RouteProviderInterface` plugin.

Kernel::plugins()

public function plugins(): array

Every configured plugin instance, including any vetoed via a `plugin.booting` listener.

Kernel::bootedPluginNames()

public function bootedPluginNames(): array

Names of the plugins whose `boot()` actually ran, in boot order.

Kernel::root()

public function root(): string

The resolved host application root directory.

Kernel::toolRegistry()

public function toolRegistry(): ?Milpa\Interfaces\Tooling\ToolRegistryInterface

The tool registry wired via `$config['toolRegistry']`, or null if the host opted out.

Kernel::commands()

public function commands(): array

Every command collected from a booted `CommandProviderInterface` plugin's `commands()`, or a `CommandProvider` plugin's `operations()` — the command-table counterpart of {@see router()}. A host CLI registers these as subcommands in addition to its own built-ins.