npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lumenflow/core

v2.18.2

Published

Core WU lifecycle tools for LumenFlow workflow framework

Downloads

5,576

Readme

@lumenflow/core

Core WU lifecycle tools for the LumenFlow workflow framework.

Installation

pnpm add @lumenflow/core

Architecture

This package follows hexagonal architecture (ports and adapters) to enable dependency injection and testing.

+---------------------------+
|        Use Cases          |  Application layer
|  ComputeContextUseCase    |
|  ValidateCommandUseCase   |
|  AnalyzeRecoveryUseCase   |
+------------+--------------+
             |
             | depends on
             v
+---------------------------+
|      Port Interfaces      |  Abstractions
|    ILocationResolver      |
|    IGitStateReader        |
|    IWuStateReader         |
+------------+--------------+
             ^
             | implements
             |
+---------------------------+
|     Adapter Classes       |  Infrastructure
|  SimpleGitLocationAdapter |
|  FileSystemWuStateAdapter |
+---------------------------+

Key Benefits:

  • Testability: Inject mock adapters for deterministic testing
  • Extensibility: Replace adapters for different environments (CI/CD, testing)
  • Maintainability: Clear separation of concerns
  • Backwards Compatible: Original functions still work unchanged

See ADR-001: Hexagonal Architecture for the full decision record.

Usage

Git Operations

import { createGitAdapter } from '@lumenflow/core';
// Or: import { createGitAdapter } from '@lumenflow/core/git';

const git = createGitAdapter({ baseDir: '/path/to/repo' });

// Check status
const status = await git.getStatus();
if (!status.isClean) {
  console.log('Modified:', status.modified);
  console.log('Untracked:', status.untracked);
}

// Commit changes
await git.add('.');
await git.commit('feat: add new feature');
await git.push();

// Fast-forward merge
await git.mergeFastForward('feature-branch');

// Branch operations
await git.createBranch('feature/new-feature', 'main');
const exists = await git.branchExists('feature/new-feature');
await git.checkout('main');
await git.deleteBranch('feature/new-feature');

Worktree Management

import { createWorktreeManager } from '@lumenflow/core';
// Or: import { createWorktreeManager } from '@lumenflow/core/git';

const worktrees = createWorktreeManager({ baseDir: '/path/to/repo' });

// Create worktree for a WU
const result = await worktrees.create({
  path: 'worktrees/operations-wu-123',
  branch: 'lane/operations/wu-123',
  startPoint: 'origin/main',
});

// List worktrees
const list = await worktrees.list();
for (const wt of list) {
  console.log(`${wt.path} -> ${wt.branch}`);
}

// Check if worktree exists
const exists = await worktrees.exists('/path/to/worktree');

// Remove worktree (handles orphan cleanup)
await worktrees.remove('worktrees/operations-wu-123');

Agent Branch Patterns

Check if a branch is an agent branch that can bypass worktree requirements. Patterns are fetched from a central registry with 7-day caching, and can be configured via .lumenflow.config.yaml.

import { isAgentBranch, isAgentBranchWithDetails, resolveAgentPatterns } from '@lumenflow/core';

// Check if branch can bypass worktree requirements (async, uses registry)
if (await isAgentBranch('claude/session-12345')) {
  console.log('Agent branch - bypass allowed');
}

// Get detailed result for observability
const result = await isAgentBranchWithDetails('claude/session-123');
if (result.isMatch) {
  console.log(`Matched via ${result.patternResult.source}`); // 'registry', 'merged', 'override', 'config', 'defaults'
  console.log(`Registry fetched: ${result.patternResult.registryFetched}`);
}

// Resolve patterns with custom options (useful for testing)
const resolved = await resolveAgentPatterns({
  configPatterns: ['my-agent/*'], // Merge with registry
  // overridePatterns: ['only-this/*'], // Replace registry entirely
  // disableAgentPatternRegistry: true, // Airgapped mode
});
console.log(resolved.patterns, resolved.source);

// Synchronous version (uses local config only, no registry fetch)
import { isAgentBranchSync } from '@lumenflow/core';
const syncResult = isAgentBranchSync('agent/task-123');

Configuration Options

In .lumenflow.config.yaml:

git:
  # Patterns to MERGE with registry (default: [])
  agentBranchPatterns:
    - 'my-custom-agent/*'
    - 'internal-tool/*'

  # Patterns that REPLACE registry entirely (optional)
  # agentBranchPatternsOverride:
  #   - 'claude/*'
  #   - 'codex/*'

  # Disable registry fetch for airgapped environments (default: false)
  # disableAgentPatternRegistry: true

Protected branches (main, master, lane/*) are never bypassed, regardless of patterns.

API Reference

GitAdapter

| Method | Description | | ----------------------------------- | ------------------------------------- | | getStatus() | Get normalized git status information | | isClean() | Check if working tree has no changes | | add(files) | Add files to staging area | | commit(message) | Commit staged changes | | push(options?) | Push to remote repository | | mergeFastForward(branch) | Fast-forward only merge | | getCurrentBranch() | Get current branch name | | branchExists(branch) | Check if branch exists | | fetch(options?) | Fetch from remote | | getCommitHash(ref?) | Get commit hash for ref | | createBranch(branch, startPoint?) | Create and checkout new branch | | checkout(branch) | Checkout existing branch | | deleteBranch(branch, options?) | Delete a branch | | raw(args) | Execute raw git command |

WorktreeManager

| Method | Description | | ------------------------ | ------------------------------- | | create(options) | Create worktree with new branch | | remove(path, options?) | Remove worktree safely | | list() | List all worktrees | | exists(path) | Check if worktree exists |

Context-Aware Validation Ports (WU-1093)

Port interfaces for context-aware validation system. These abstractions allow external users to inject custom implementations.

import type {
  ILocationResolver,
  IGitStateReader,
  IWuStateReader,
  ICommandRegistry,
  IRecoveryAnalyzer,
} from '@lumenflow/core';

Adapter Classes (WU-1094)

Concrete adapter implementations that wrap the existing functions:

import {
  // Context adapters
  SimpleGitLocationAdapter,
  SimpleGitStateAdapter,
  FileSystemWuStateAdapter,
  // Validation adapters
  CommandRegistryAdapter,
  // Recovery adapters
  RecoveryAnalyzerAdapter,
} from '@lumenflow/core';

// Create adapters implementing port interfaces
const locationResolver = new SimpleGitLocationAdapter();
const gitStateReader = new SimpleGitStateAdapter();
const wuStateReader = new FileSystemWuStateAdapter();
const commandRegistry = new CommandRegistryAdapter();
const recoveryAnalyzer = new RecoveryAnalyzerAdapter();

// Use adapters
const location = await locationResolver.resolveLocation();
const gitState = await gitStateReader.readGitState();
const wuState = await wuStateReader.readWuState('WU-1094', '/repo');
const cmdDef = commandRegistry.getCommandDefinition('wu:done');
const analysis = await recoveryAnalyzer.analyzeRecovery(context);

Use Cases with Dependency Injection (WU-1094)

Use case classes with constructor injection enable testing with mock adapters:

import {
  ComputeContextUseCase,
  ValidateCommandUseCase,
  AnalyzeRecoveryUseCase,
  SimpleGitLocationAdapter,
  SimpleGitStateAdapter,
  FileSystemWuStateAdapter,
  CommandRegistryAdapter,
  RecoveryAnalyzerAdapter,
} from '@lumenflow/core';

// Manual wiring with real adapters
const computeContext = new ComputeContextUseCase(
  new SimpleGitLocationAdapter(),
  new SimpleGitStateAdapter(),
  new FileSystemWuStateAdapter(),
);

const validateCommand = new ValidateCommandUseCase(new CommandRegistryAdapter());

const analyzeRecovery = new AnalyzeRecoveryUseCase(new RecoveryAnalyzerAdapter());

// Execute use cases
const context = await computeContext.execute({ wuId: 'WU-1094' });
const validation = await validateCommand.execute('wu:done', context);
const recovery = await analyzeRecovery.execute(context);

DI Factory Functions (WU-1094)

Factory functions create fully wired use cases with default or custom adapters:

import {
  createComputeContextUseCase,
  createValidateCommandUseCase,
  createAnalyzeRecoveryUseCase,
} from '@lumenflow/core';

// Use defaults - simplest approach
const useCase = createComputeContextUseCase();
const context = await useCase.execute({ wuId: 'WU-1094' });

// Inject custom adapters for testing
const mockLocationResolver = {
  resolveLocation: async () => ({
    type: 'main' as const,
    cwd: '/test',
    gitRoot: '/test',
    mainCheckout: '/test',
    worktreeName: null,
    worktreeWuId: null,
  }),
};

const testUseCase = createComputeContextUseCase({
  locationResolver: mockLocationResolver,
  // gitStateReader and wuStateReader use defaults
});

Convenience Functions (WU-1094)

For simple use cases, backwards compatible functions are available:

import { computeWuContext, validateCommand, analyzeRecoveryIssues } from '@lumenflow/core';

// Compute context (uses default adapters internally)
const context = await computeWuContext({ wuId: 'WU-1094' });

// Validate a command
const validation = await validateCommand('wu:done', context);
if (!validation.valid) {
  console.error(validation.errors[0].message);
}

// Analyze for recovery issues
const recovery = await analyzeRecoveryIssues(context);
if (recovery.hasIssues) {
  for (const action of recovery.actions) {
    console.log(`Fix: ${action.command}`);
  }
}

Domain Schemas (Zod)

Runtime validation schemas for domain types. Types are inferred from Zod schemas using z.infer<>.

import {
  // Context schemas
  LocationContextSchema,
  GitStateSchema,
  WuStateResultSchema,
  SessionStateSchema,
  WuContextSchema,

  // Validation schemas
  ValidationErrorSchema,
  ValidationWarningSchema,
  ValidationResultSchema,
  CommandPredicateConfigSchema,
  CommandDefinitionConfigSchema,

  // Recovery schemas
  RecoveryIssueSchema,
  RecoveryActionSchema,
  RecoveryAnalysisSchema,

  // Types (inferred from schemas)
  type LocationContext,
  type GitState,
  type WuStateResult,
  type ValidationError,
  type RecoveryAnalysis,
} from '@lumenflow/core';

// Validate runtime data
const result = LocationContextSchema.safeParse(unknownData);
if (result.success) {
  const location: LocationContext = result.data;
  console.log(`Type: ${location.type}, CWD: ${location.cwd}`);
}

Testing with Custom Adapters

The hexagonal architecture makes testing straightforward. Inject mock adapters to create deterministic tests without file system or git dependencies.

Example: Testing with Mock Adapters

import { describe, it, expect } from 'vitest';
import { createComputeContextUseCase } from '@lumenflow/core';
import type { ILocationResolver, IGitStateReader, IWuStateReader } from '@lumenflow/core';

describe('ComputeContextUseCase', () => {
  it('should detect worktree context', async () => {
    // Create mock adapters
    const mockLocation: ILocationResolver = {
      resolveLocation: async () => ({
        type: 'worktree',
        cwd: '/test/worktrees/ops-wu-1095',
        gitRoot: '/test/worktrees/ops-wu-1095',
        mainCheckout: '/test',
        worktreeName: 'ops-wu-1095',
        worktreeWuId: 'WU-1095',
      }),
    };

    const mockGitState: IGitStateReader = {
      readGitState: async () => ({
        branch: 'lane/operations/wu-1095',
        isDetached: false,
        isDirty: false,
        hasStaged: false,
        ahead: 1,
        behind: 0,
        tracking: 'origin/lane/operations/wu-1095',
        modifiedFiles: [],
        hasError: false,
        errorMessage: null,
      }),
    };

    const mockWuState: IWuStateReader = {
      readWuState: async () => ({
        id: 'WU-1095',
        status: 'in_progress',
        lane: 'Content: Documentation',
        title: 'Test WU',
        yamlPath: '/test/docs/04-operations/tasks/wu/WU-1095.yaml',
        isConsistent: true,
        inconsistencyReason: null,
      }),
    };

    // Create use case with mocks
    const useCase = createComputeContextUseCase({
      locationResolver: mockLocation,
      gitStateReader: mockGitState,
      wuStateReader: mockWuState,
    });

    // Execute
    const context = await useCase.execute({ wuId: 'WU-1095' });

    // Assert - fully deterministic
    expect(context.location.type).toBe('worktree');
    expect(context.location.worktreeWuId).toBe('WU-1095');
    expect(context.wu?.status).toBe('in_progress');
  });
});

Example: CI/CD Custom Adapter

import type { ILocationResolver, LocationContext } from '@lumenflow/core';
import { createComputeContextUseCase } from '@lumenflow/core';

// CI environments always run in main checkout
class CILocationResolver implements ILocationResolver {
  constructor(private readonly repoPath: string) {}

  async resolveLocation(cwd?: string): Promise<LocationContext> {
    return {
      type: 'main',
      cwd: cwd || this.repoPath,
      gitRoot: this.repoPath,
      mainCheckout: this.repoPath,
      worktreeName: null,
      worktreeWuId: null,
    };
  }
}

// Usage in CI
const useCase = createComputeContextUseCase({
  locationResolver: new CILocationResolver('/github/workspace'),
});

Features

  • Type-safe: Full TypeScript support with detailed type definitions
  • Dependency injection: Easy to test with mock adapters
  • Hexagonal architecture: Port interfaces for external injection
  • Safe worktree cleanup: Handles orphan directories and corrupted metadata
  • Modern: Node 22+, ESM-only, strict TypeScript
  • Zod schemas: Runtime validation for all domain types

Further Reading

Status

This package is under active development. Current features:

  • Git operations (GitAdapter)
  • Worktree management (WorktreeManager)
  • Context-aware validation (WU-1090)
  • Hexagonal architecture with DI (INIT-002)
  • Modern tooling (Node 22, ESLint 9, TypeScript 5.7, Vitest 4)
  • Security and code quality linting

License

Apache-2.0