@intentic/engine
v1.248.0
Published
Stateless reconcile engine: plan/apply, the Provider SPI, and the reconcile loop.
Readme
@intentic/engine
The stateless reconcile engine. It walks a DesiredStateGraph in dependency order and converges it through the Provider SPI: never constructing providers itself, only consuming a ResourceType → Provider map. Depends on @intentic/graph + @intentic/resources; the real providers live in @intentic/providers.
Responsibilities
apply, converge once: per node,read→diff→create/update/noop, gating on readiness.plan, dry run: classify every node without mutating infra.reconcile: loop apply→read until a plan reads all-noop ("state reads true"), returning aConvergeResult.- Define the Provider SPI the rest of the system implements:
Provider,Providers,Observed,DiffResult,ProviderContext. - Emit structured
EngineEvents (for the CLI's ndjson/json output) and handle readiness, orphans, and pruning.
Key files
- src/reconcile/apply.ts / src/reconcile/plan.ts / src/reconcile/reconcile-loop.ts: the converge/dry-run/loop logic.
- src/provider.ts / src/types.ts: the SPI and engine types (
Provider,DiffResult,EngineConfig,Step,Orphan). - src/readiness.ts:
httpProbe/waitReady(readiness gates), andpollUntil, the one waiting loop every "is it up yet" in the engine and the providers is written on. - src/resolve-inputs.ts: resolve refs/secrets into concrete provider inputs.
- src/reconcile/orphans.ts / src/reconcile/prune.ts (drift cleanup; src/providers)
createFakeProviders(in-memory SPI for tests).
How it fits
The execution core. state-resolver produces the graph; providers supplies the concrete SPI map; the cli wires them together and runs reconcile. The engine stays infra-agnostic: all I/O is behind the SPI.
Conventions & gotchas
- The engine never imports
providers: it takes aProvidersmap as input, so it can run against fakes. diffmust be pure (read does the I/O); apply is the only mutating step.EngineEventis part of the public contract for embedders. See ARCHITECTURE.md.
