Skip to content

10. Runtime Execution

The runtime is a domain-neutral interpreter. It resolves qualified Blueprint identities; it never branches on names such as area, batch, or pharma.

Build a protocol request

dart
import 'package:vyuh_blueprint_protocol/'
    'vyuh_blueprint_protocol.dart' as protocol;
import 'package:vyuh_blueprint_server/'
    'vyuh_blueprint_server.dart';

final request = protocol.ActionRequest(
  id: 'request-001',
  source: protocol.RequestSource.ui,
  context: protocol.RequestContext(
    actorId: 'user-42',
    actorRoles: const ['quality_reviewer'],
    actorSource: 'directory',
    tenantId: 'tenant-1',
    siteId: 'hyderabad',
    reasonCode: 'AREA_READY',
    justification: 'Qualification review completed.',
    occurredAt: DateTime.now().toUtc(),
    correlationId: 'change-control-107',
  ),
  resume: const protocol.ActionResumePolicy(
    idempotencyKey: 'activate:area-201:revision-7',
  ),
  commands: const [
    protocol.ActionCommand(
      module: 'ops',
      entity: 'area',
      facet: 'governance',
      action: 'activate',
      entityId: 'area-201',
      idempotencyKey: 'activate:area-201:revision-7',
    ),
  ],
);

One request can carry multiple commands. RequestLineage and ExecutionLimits bound recursive effects and workflows.

Use the common runtime boundary

dart
final BlueprintRuntime runtime = BlueprintRuntimeEngine(
  blueprint: blueprint,
  policies: policies,
  evaluators: {
    'ops.area.release': areaReleaseEvaluator,
  },
);

final manifest = await runtime.manifest();
final capabilities = await runtime.capabilities(request.context);
final plan = await runtime.plan(request);
final preflight = await runtime.preflight(request);
final record = await runtime.execute(request);
final explanation = await runtime.explain(record.id);

The same interface is used by the in-process planner, persistent database executor, route modules, and tests:

dart
abstract interface class BlueprintRuntime {
  Future<BlueprintManifest> manifest();
  Future<ContextualCapabilityManifest> capabilities(RequestContext context);
  Future<ExecutionPlan> plan(ActionRequest request);
  Future<ActionRecord> preflight(ActionRequest request);
  Future<ActionRecord> execute(ActionRequest request);
  Future<ExecutionExplanation> explain(String actionRecordId);
}

Read the plan before the outcome

ExecutionPlan contains:

  • qualified commands;
  • phase-grouped rules;
  • effective policies;
  • lock set;
  • snapshot targets;
  • write set;
  • pre/post invariant checks;
  • runtime effects such as DB, audit, outbox, realtime, and dry-run records;
  • integrity findings.

This lets UI, CLI, and Studio show “what would happen?” without executing.

Persistent transaction order

text
accept and deduplicate request
  -> resolve immutable Blueprint revision
  -> resolve and snapshot effective configuration
  -> plan commands, locks, writes, evidence, events, and effects
  -> preflight access, policy, lifecycle, data, and evidence
  -> lock current state
  -> evaluate before-commit rules and invariants
  -> stage state, evidence manifests, events, audit, action record, outbox
  -> evaluate candidate-state postconditions
  -> commit atomically
  -> dispatch external effects
  -> append receipts and deferred findings

Strict effects belong to the atomic boundary. Eventual work leaves through the outbox after commit.

Idempotency and concurrency are language-independent

  • A stable idempotency key deduplicates retries.
  • Expected versions and locks prevent lost updates.
  • A committed request can return the prior record.
  • An incomplete request can resume pending work according to ActionResumePolicy.
  • Recursion depth, command count, and effect count are bounded by ExecutionLimits.

These are runtime laws, not Ops-specific rules.

BlueprintRuntimeEngine builds manifests, capabilities, deterministic plans, preflight records, decisions, events, evidence, snapshots, and explanations. BlueprintProtocolDbExecutor supplies locked row state, applies the plan's database mutations, and persists the runtime ledger in one transaction. OutboxRunner and OutboxDispatcher process committed delivery work using the effect idempotency and attempt state stored by that transaction.

Checkpoint

Create one request and inspect:

  1. plan.commands.single.phases;
  2. preflight.failures;
  3. record.ruleRecords, eventRecords, and effectRecords;
  4. explanation.ruleResults.

Change the actor or lifecycle state and confirm that the plan identity remains stable while the decision outcome changes.

Next: Evidence, audit, and replay.

References: Runtime Contracts · Protocol.

Blue is the Vyuh Blueprint documentation surface.