LumenFlow provides TypeScript API documentation generated from source code using TypeDoc.
@lumenflow/core
WU lifecycle, state machine, validators, configuration
@lumenflow/cli
Command implementations, argument parsing
@lumenflow/packs-software-delivery
WU lifecycle, initiatives, delivery metrics, and workflow memory
@lumenflow/agent
Skill loading, agent definitions, verification
WU lifecycle operations are implemented as CLI commands, not as an importable
@lumenflow/core function API:
pnpm wu:create --id WU-042 --title "Add email validation" --lane "Framework: Core"
pnpm wu:claim --id WU-042 --lane "Framework: Core"
pnpm wu:done --id WU-042
import { assertTransition } from '@lumenflow/core' ;
// Throws if the transition is illegal; returns void if it is valid.
assertTransition ( 'ready' , 'in_progress' , 'WU-042' );
import { getConfig , validateConfigFile } from '@lumenflow/core' ;
// Load resolved config (workspace.yaml's software_delivery block + schema defaults)
const config = getConfig ({ projectRoot : '/path/to/repository' });
// Validate a config file directly
const { valid , errors } = validateConfigFile ( '/path/to/workspace.yaml' );
if ( ! valid) {
console. error ( 'Config issues:' , errors);
}
getRepoPlansDir, getRepoPlanPath, normalizeSpecRef, validateSpecRefs, and
normalizeSpecRefs now require an explicit workspace root. This is a
source-breaking public API change and is classified for the next major release.
Passing the root prevents plan lookup and validation from silently following an
unrelated process working directory.
Before:
import { normalizeSpecRef } from '@lumenflow/core/lumenflow-home' ;
import { validateSpecRefs } from '@lumenflow/core/wu-create-validators' ;
const planPath = normalizeSpecRef ( 'lumenflow://plans/WU-042-plan.md' );
const validation = validateSpecRefs ([ 'lumenflow://plans/WU-042-plan.md' ]);
After:
import { normalizeSpecRef } from '@lumenflow/core/lumenflow-home' ;
import { validateSpecRefs } from '@lumenflow/core/wu-create-validators' ;
const workspaceRoot = '/path/to/repository' ;
const planPath = normalizeSpecRef ( 'lumenflow://plans/WU-042-plan.md' , workspaceRoot);
const validation = validateSpecRefs ([ 'lumenflow://plans/WU-042-plan.md' ], workspaceRoot);
The asynchronous delegation registry discovery API remains backward compatible:
resolveCanonicalDelegationRegistryDir() can still be called without an argument.
Code that already knows its checkout should continue to pass that directory
explicitly.
import { syncNdjsonTelemetryToCloud } from '@lumenflow/core/telemetry' ;
import { emitCostEvent } from '@lumenflow/packs-software-delivery' ;
import type { CostEvent , CostSummary } from '@lumenflow/packs-software-delivery/metrics' ;
const event : CostEvent = {
timestamp : new Date (). toISOString (),
sourceType : 'cost' ,
operation : 'llm.classification' ,
model : 'gpt-4o-mini' ,
inputTokens : 1200 ,
outputTokens : 320 ,
costUsd : 0.0421 ,
wuId : 'WU-101' ,
agentId : 'agent-1' ,
sessionId : 'session-abc' ,
};
emitCostEvent ({
timestamp : event. timestamp ,
operation : event. operation ,
model : event. model ,
input_tokens : event. inputTokens ,
output_tokens : event. outputTokens ,
cost_usd : event. costUsd ,
wu_id : event. wuId ,
agent_id : event. agentId ,
session_id : event. sessionId ,
});
// Later: include costs.ndjson alongside other telemetry sources in cloud sync
await syncNdjsonTelemetryToCloud ();
Local operator summary command:
pnpm cost:summary
pnpm cost:summary --json
import type { HeartbeatInput , HeartbeatResult } from '@lumenflow/control-plane-sdk' ;
const heartbeatRequest : HeartbeatInput = {
workspace_id : 'workspace-a' ,
session_id : 'session-a' ,
agent_id : 'agent-1' ,
wu_id : 'WU-102' ,
health : {
busy : false ,
stalled : false ,
last_progress_at : new Date (). toISOString (),
},
};
const heartbeatResponse : HeartbeatResult = {
status : 'ok' ,
server_time : new Date (). toISOString (),
next_heartbeat_ms : 30000 ,
assignment : {
wu_id : 'WU-102' ,
action : 'continue' ,
hint : 'server-directed cadence' ,
},
budget_remaining_usd : 42.5 ,
coalesced_signals : 2 ,
};
import type { RegisterSessionInput , SessionSummary } from '@lumenflow/control-plane-sdk' ;
const registerSessionInput : RegisterSessionInput = {
workspace_id : 'workspace-a' ,
session_id : 'session-a' ,
agent_id : 'agent-1' ,
started_at : new Date (). toISOString (),
lane : 'Framework: Core Lifecycle' ,
wu_id : 'WU-103' ,
client_type : 'claude-code' ,
capabilities : [ 'session_lifecycle' , 'heartbeat' ],
agent_version : '3.10.0' ,
host_id : 'host-01' ,
metadata : {
client_type : 'claude-code' ,
capabilities : [ 'session_lifecycle' , 'heartbeat' ],
agent_version : '3.10.0' ,
host_id : 'host-01' ,
},
};
const sessionSummary : SessionSummary = {
workspace_id : 'workspace-a' ,
session_id : 'session-a' ,
agent_id : 'agent-1' ,
started_at : new Date (). toISOString (),
active : true ,
client_type : 'claude-code' ,
capabilities : [ 'session_lifecycle' , 'heartbeat' ],
agent_version : '3.10.0' ,
host_id : 'host-01' ,
metadata : {
client_type : 'claude-code' ,
capabilities : [ 'session_lifecycle' , 'heartbeat' ],
agent_version : '3.10.0' ,
host_id : 'host-01' ,
},
};
import {
resolveLocation ,
readGitState ,
readWuState ,
validateContext ,
LocationType ,
} from '@lumenflow/core' ;
// Resolve current location
const location = await resolveLocation ();
if (location. type === LocationType. WORKTREE ) {
console. log ( `In worktree: ${ location . worktreeName } ` );
}
// Read git state
const gitState = await readGitState ();
if (gitState. isDirty ) {
console. log ( 'Uncommitted changes present' );
}
// Full context validation
const result = await validateContext ({
command : 'wu:done' ,
wuId : 'WU-042' ,
});
import { isAgentBranch , isAgentBranchWithDetails , resolveAgentPatterns } from '@lumenflow/core' ;
// Check if branch is an agent branch
const isAgent = await isAgentBranch ( 'claude/session-12345' );
// true
// Get detailed result
const result = await isAgentBranchWithDetails ( 'claude/session-12345' );
console. log (result. patternResult . source );
// 'registry' | 'merged' | 'override' | 'config' | 'defaults'
The Software Delivery pack is the canonical owner of delivery/workflow memory. The
@lumenflow/memory package remains available as a deprecated compatibility shell, but new code
should use the pack subpath below.
import { startSession , type StartSessionResult } from '@lumenflow/packs-software-delivery/memory' ;
const projectRoot = '/path/to/repository' ;
const result : StartSessionResult = await startSession (projectRoot, {
wuId : 'WU-042' ,
agentType : 'claude-code' , // example; use your project's configured client
contextTier : 'full' ,
});
console. log (result. session . id );
import { createCheckpoint } from '@lumenflow/packs-software-delivery/memory' ;
const result = await createCheckpoint ( '/path/to/repository' , {
wuId : 'WU-042' ,
note : 'Tests passing, starting implementation' ,
progress : 'Validation tests are green' ,
nextSteps : 'Wire the validator into the form' ,
});
console. log (result. checkpoint . id );
import {
createSignal ,
loadInboxSignalViews ,
type Signal ,
} from '@lumenflow/packs-software-delivery/memory' ;
const projectRoot = '/path/to/repository' ;
const created = await createSignal (projectRoot, {
wuId : 'WU-042' ,
message : 'Implementation complete' ,
type : 'progress' ,
sender : 'codex:implementer' ,
});
const inbox = await loadInboxSignalViews (projectRoot, {
wuId : 'WU-042' ,
unreadOnly : true ,
});
const signal : Signal = created. signal ;
console. log (signal. id , inbox. length );
There is no loadSkill/listSkills/validateSkill API in @lumenflow/agent.
Skill definitions are validated by validateSkillFile/validateAllSkills in
@lumenflow/cli/src/validate-agent-skills.ts, an internal helper not
currently exposed through the package’s public exports. Invoke it via the
internal CLI entry point instead:
node tools/cli-entry.mjs validate-agent-skills
import { verifyWUComplete , type VerificationResult } from '@lumenflow/agent' ;
// Verify WU completion
const result : VerificationResult = verifyWUComplete ( 'WU-042' );
if (result. complete ) {
console. log ( 'All acceptance criteria met' );
} else {
console. log ( 'Failed:' , result. failures );
}
The CLI package is primarily used via commands, but exports some utilities:
import { printHeader , createStatusTable } from '@lumenflow/cli' ;
// Print the LumenFlow CLI banner
printHeader ({ version : '5.19.0' });
// Format a status table
const table = createStatusTable ({
head : [ 'ID' , 'Status' ],
rows : [
[ 'WU-042' , 'done' ],
[ 'WU-043' , 'ready' ],
],
});
console. log (table);
interface WuSpec {
id : string ;
title : string ;
lane : string ;
type : 'feature' | 'bug' | 'documentation' | 'refactor' ;
status : WuStatus ;
priority : 'P0' | 'P1' | 'P2' | 'P3' ;
description : string ;
acceptance : string [];
code_paths : string [];
test_paths ?: {
unit ?: string [];
integration ?: string [];
e2e ?: string [];
};
dependencies ?: string [];
blocked_by ?: string [];
created : string ;
assigned_to ?: string ;
notes ?: string ;
}
enum WuStatus {
READY = 'ready' ,
IN_PROGRESS = 'in_progress' ,
BLOCKED = 'blocked' ,
WAITING = 'waiting' ,
DONE = 'done' ,
}
interface LocationContext {
type : LocationType ;
cwd : string ;
gitRoot : string ;
mainCheckout : string ;
worktreeName : string | null ;
worktreeWuId : string | null ;
}
enum LocationType {
MAIN = 'main' ,
WORKTREE = 'worktree' ,
DETACHED = 'detached' ,
UNKNOWN = 'unknown' ,
}
interface GitState {
branch : string | null ;
isDetached : boolean ;
isDirty : boolean ;
hasStaged : boolean ;
ahead : number ;
behind : number ;
tracking : string | null ;
modifiedFiles : string [];
hasError : boolean ;
errorMessage : string | null ;
}
To generate TypeDoc documentation locally:
# Install TypeDoc (if not already)
pnpm add -D typedoc typedoc-plugin-markdown
# Generate docs
pnpm typedoc --out docs/api packages/@lumenflow/ * /src/index.ts