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, 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.

Before INIT-056, 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 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 what ADR-010 calls “one initiative state model, many launchers.”