Skip to content

Control-plane SDK

@lumenflow/control-plane-sdk is the published package that defines the orchestration state contract every LumenFlow surface speaks. The package is intentionally small — it owns the state vocabulary, the artifact document shapes, schema-versioned event vocabulary, and the parsers that validate them.

pnpm add @lumenflow/control-plane-sdk

When you read a status.json, receive an MCP coordination-tool payload, or integrate a third-party launcher or remote control surface, the SDK is what guarantees the shape.

import {
  ORCHESTRATION_STATUS_VALUES,
  ORCHESTRATION_NEXT_SAFE_ACTION_TYPES,
  ORCHESTRATION_CLAIM_MODES,
  ORCHESTRATION_HANDOFF_FORMATS,
} from '@lumenflow/control-plane-sdk';

ORCHESTRATION_STATUS_VALUES.CONTAMINATED; // 'contaminated'
ORCHESTRATION_NEXT_SAFE_ACTION_TYPES.FINISH_WU; // 'finish_wu'
ORCHESTRATION_CLAIM_MODES.BRANCH_PR; // 'branch-pr'
ORCHESTRATION_HANDOFF_FORMATS.MARKDOWN; // 'markdown'

These are the single source of truth for the state machine. @lumenflow/initiatives re-exports them as ORCHESTRATION_EXECUTION_STATES for intra-package readability, but the values are identical.

import type {
  OrchestrationPlanDocument,
  OrchestrationLaunchDocument,
  OrchestrationStatusDocument,
  OrchestrationLaunchReceipt,
  OrchestrationNextSafeAction,
  OrchestrationStatusWu,
} from '@lumenflow/control-plane-sdk';

These are the shapes that plan.json, launch.json, and status.json emit. See the artifact bundle page for how each one is layered.

The SDK ships validating parsers, not pass-through casts:

import {
  parseOrchestrationPlanDocument,
  parseOrchestrationLaunchDocument,
  parseOrchestrationStatusDocument,
} from '@lumenflow/control-plane-sdk';

const raw = JSON.parse(fs.readFileSync('status.json', 'utf8'));
const status = parseOrchestrationStatusDocument(raw);
// status is now typed + validated; unknown orchestration_state values throw.

Legacy 'ready' is normalized to 'eligible' so older status files stay readable.

import { ORCHESTRATION_ARTIFACT_DIR } from '@lumenflow/control-plane-sdk';
// '.lumenflow/artifacts/orchestration'

Used by the CLI monitor, MCP adapters, and any downstream tool that needs to find orchestration bundles on disk.

The SDK is the .dev-side source of truth for the opaque, semantic routing and residency labels that campus governance reasons about (INIT-MOONSHOT MD5). LumenFlow Cloud mirrors these with a Zod .strict() extension; cloud owns the schema change and migration, while this package owns the type contract, so both sides compile in lockstep.

import {
  DATA_EGRESS_CLASS_VALUES,
  CAMPUS_AFFINITY_VALUES,
  RESIDENCY_CLASS_VALUES,
  type DataEgressClass,
  type CampusAffinity,
  type ResidencyClass,
} from '@lumenflow/control-plane-sdk';

// Cloud builds the mirrored enum directly from the source of truth:
// z.enum(DATA_EGRESS_CLASS_VALUES)

Per the campus governance boundary’s vendor-name-free invariant, every label is opaque and semantic — it describes what a constraint means, never who provides the compute. No vendor brand string may appear in any value; vendor identity, where it must exist, lives in workspace-owned configuration mapped behind these labels.

TypeValues (most → least restrictive)Meaning
DataEgressClasscampus_bound, campus_restricted, region_restricted, unrestrictedWhere data is permitted to flow. The resolver branches on this class, never on a vendor name.
CampusAffinityrequired, preferred, noneHow strongly work must be scheduled on a specific campus. A required affinity that cannot be met is refused, not silently downgraded.
ResidencyClasscampus_local, region_local, multi_region, globalThe geographic / jurisdictional scope within which data must remain.

The _VALUES tuples are exported as const so cloud can build the mirrored Zod enum directly from this source of truth, guaranteeing the two sides never drift.

import { EVENT_SCHEMA_FAMILIES, validateControlPlaneEvent } from '@lumenflow/control-plane-sdk';

const result = validateControlPlaneEvent({
  schema_version: 2,
  kind: 'brief:token_reported',
  timestamp: '2026-05-13T12:00:00.000Z',
  event_id: 'evt-example',
  wu_id: 'WU-123',
  client_name: 'codex-cli',
  prompt_hash: 'sha256:abc123',
  total_tokens: 1280,
  sections: [{ name: 'Stable Prefix', tokens: 420, stable: true }],
});

if (!result.valid) {
  console.error(result.issues);
}

console.log(EVENT_SCHEMA_FAMILIES.map((family) => family.id));

The committed JSON Schemas live under .lumenflow/schemas/events/. They are the same control-plane contract for local CLI views, self-hosted dashboards, third-party observability, and hosted consumers.

Validate event files locally with:

pnpm events:validate
pnpm events:validate .lumenflow/schemas/events/fixtures/valid
pnpm events:validate path/to/events.ndjson

The validator rejects missing schema_version, unknown kind, and schema-invalid payloads. The default command validates the committed valid fixtures; invalid fixtures are available for manual non-zero smoke checks.

The measurement event family includes brief:token_reported records emitted by wu:brief --report-tokens. Those records are appended to .lumenflow/telemetry/brief-metrics.ndjson for local inspection with pnpm cost:summary --brief; any hosted or self-hosted dashboard consumes the same schema rather than a dashboard-specific export.

Before the SDK existed, each LumenFlow package carried its own orchestration types. The CLI collapsed rich states to in_progress. MCP ran a second classifier that silently drifted from the initiatives reconciler. Remote parity was aspirational — every surface paraphrased the state vocabulary slightly differently.

The SDK fixes that by being the only source of:

  • The 13-value orchestration state vocabulary.
  • The 5-value next-safe-action vocabulary (launch_wu, finish_wu, recover_wu, relaunch_wu, wait).
  • The snake_case JSON schema every persisted artifact uses.
  • The schema-versioned event catalog for control-plane measurement and routing.
  • The parsers that enforce that schema at every boundary.

@lumenflow/initiatives imports from the SDK. @lumenflow/cli imports from the SDK. @lumenflow/mcp imports from the SDK and from @lumenflow/initiatives (so it shares the reconciler). Remote control surfaces import from the SDK too. One contract, many consumers.

The same OrchestrationStatusDocument that your local CLI writes to status.json is the same contract a remote control surface can expose over HTTP or another transport. That means:

  • A WU you start locally can hand off to another surface without reshaping the state.
  • An agent that reads MCP coordination tools today can talk to a remote orchestrator tomorrow tomorrow without code changes.
  • Third-party launchers that implement the SDK contract get to participate in the same state machine — not their own dialect of it.

This is the principle of “one initiative state model, many launchers.”

Events use kind as the discriminant and schema_version as the compatibility switch. Additive payload fields are compatible. Changing the required shape of an existing kind needs a version bump or a parallel compatibility path. New measurement emitters must add schema coverage before they emit measurement, routing, skill-hint, or prompt-optimizer events.