Files
automaker/docs/llm-shared-packages.md
Kacper 7ad7b63da2 docs: add comprehensive documentation for shared packages
- Added README.md for all 6 shared packages:
  - @automaker/types: Type definitions and interfaces
  - @automaker/utils: Utility functions (logger, error handling, images)
  - @automaker/platform: Platform utilities (paths, subprocess, security)
  - @automaker/model-resolver: Claude model resolution
  - @automaker/dependency-resolver: Feature dependency ordering
  - @automaker/git-utils: Git operations and diff generation

- Removed MIT license from all package.json files (using custom dual license)

- Created comprehensive LLM guide (docs/llm-shared-packages.md):
  - When to use each package
  - Import patterns and examples
  - Common usage patterns
  - Migration checklist
  - Do's and don'ts for LLMs

Documentation helps developers and AI assistants understand package purpose,
usage, and best practices.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-19 23:52:42 +01:00

12 KiB

AutoMaker Shared Packages - LLM Guide

This guide helps AI assistants understand how to use AutoMaker's shared packages effectively.

Package Overview

AutoMaker uses a monorepo structure with shared packages in libs/:

libs/
├── types/              # Type definitions (no dependencies)
├── utils/              # Utility functions
├── platform/           # Platform utilities
├── model-resolver/     # Claude model resolution
├── dependency-resolver/# Feature dependency resolution
└── git-utils/          # Git operations

When to Use Each Package

@automaker/types

Use when: You need type definitions for any AutoMaker concept.

Import for:

  • Feature - Feature interface with all properties
  • ExecuteOptions - Claude agent execution options
  • ConversationMessage - Chat message format
  • ErrorType, ErrorInfo - Error handling types
  • CLAUDE_MODEL_MAP - Model alias to ID mapping
  • DEFAULT_MODELS - Default model configurations

Example:

import type { Feature, ExecuteOptions } from '@automaker/types';

Never import from: services/feature-loader, providers/types

@automaker/utils

Use when: You need common utilities like logging, error handling, or image processing.

Import for:

  • createLogger(context) - Structured logging
  • isAbortError(error) - Error type checking
  • classifyError(error) - Error classification
  • buildPromptWithImages() - Prompt building with images
  • readImageAsBase64() - Image handling
  • extractTextFromContent() - Message parsing

Example:

import { createLogger, classifyError } from '@automaker/utils';

Never import from: lib/logger, lib/error-handler, lib/prompt-builder, lib/image-handler

@automaker/platform

Use when: You need to work with AutoMaker's directory structure or spawn processes.

Import for:

  • getAutomakerDir(projectPath) - Get .automaker directory
  • getFeaturesDir(projectPath) - Get features directory
  • getFeatureDir(projectPath, featureId) - Get specific feature directory
  • ensureAutomakerDir(projectPath) - Create .automaker if needed
  • spawnJSONLProcess() - Spawn process with JSONL output
  • initAllowedPaths() - Security path validation

Example:

import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform';

Never import from: lib/automaker-paths, lib/subprocess-manager, lib/security

@automaker/model-resolver

Use when: You need to convert model aliases to full model IDs.

Import for:

  • resolveModelString(modelOrAlias) - Convert alias to full ID
  • DEFAULT_MODELS - Access default models

Example:

import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver';

// Convert user input to model ID
const modelId = resolveModelString('sonnet'); // → 'claude-sonnet-4-20250514'

Never import from: lib/model-resolver

Model aliases:

  • haikuclaude-haiku-4-5 (fast, simple tasks)
  • sonnetclaude-sonnet-4-20250514 (balanced, recommended)
  • opusclaude-opus-4-5-20251101 (maximum capability)

@automaker/dependency-resolver

Use when: You need to order features by dependencies or check if dependencies are satisfied.

Import for:

  • resolveDependencies(features) - Topological sort with priority
  • areDependenciesSatisfied(feature, allFeatures) - Check if ready to execute
  • getBlockingDependencies(feature, allFeatures) - Get incomplete dependencies

Example:

import { resolveDependencies, areDependenciesSatisfied } from '@automaker/dependency-resolver';

const { orderedFeatures, hasCycle } = resolveDependencies(features);
if (!hasCycle) {
  for (const feature of orderedFeatures) {
    if (areDependenciesSatisfied(feature, features)) {
      await execute(feature);
    }
  }
}

Never import from: lib/dependency-resolver

Used in:

  • Auto-mode feature execution (server)
  • Board view feature ordering (UI)

@automaker/git-utils

Use when: You need git operations, status parsing, or diff generation.

Import for:

  • isGitRepo(path) - Check if path is a git repository
  • parseGitStatus(output) - Parse git status --porcelain output
  • getGitRepositoryDiffs(path) - Get complete diffs (tracked + untracked)
  • generateSyntheticDiffForNewFile() - Create diff for untracked file
  • listAllFilesInDirectory() - List files excluding build artifacts

Example:

import { isGitRepo, getGitRepositoryDiffs } from '@automaker/git-utils';

if (await isGitRepo(projectPath)) {
  const { diff, files, hasChanges } = await getGitRepositoryDiffs(projectPath);
  console.log(`Found ${files.length} changed files`);
}

Never import from: routes/common

Handles:

  • Binary file detection
  • Large file handling (>1MB)
  • Untracked file diffs
  • Non-git directory support

Common Patterns

Creating a Feature Executor

import type { Feature, ExecuteOptions } from '@automaker/types';
import { createLogger, classifyError } from '@automaker/utils';
import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver';
import { areDependenciesSatisfied } from '@automaker/dependency-resolver';
import { getFeatureDir } from '@automaker/platform';

const logger = createLogger('FeatureExecutor');

async function executeFeature(
  feature: Feature,
  allFeatures: Feature[],
  projectPath: string
) {
  // Check dependencies
  if (!areDependenciesSatisfied(feature, allFeatures)) {
    logger.warn(`Dependencies not satisfied for ${feature.id}`);
    return;
  }

  // Resolve model
  const model = resolveModelString(feature.model, DEFAULT_MODELS.autoMode);

  // Get feature directory
  const featureDir = getFeatureDir(projectPath, feature.id);

  try {
    // Execute with Claude
    const options: ExecuteOptions = {
      model,
      temperature: 0.7
    };

    await runAgent(featureDir, options);

    logger.info(`Feature ${feature.id} completed`);
  } catch (error) {
    const errorInfo = classifyError(error);
    logger.error(`Feature ${feature.id} failed:`, errorInfo.message);
  }
}

Analyzing Git Changes

import { getGitRepositoryDiffs, parseGitStatus } from '@automaker/git-utils';
import { createLogger } from '@automaker/utils';

const logger = createLogger('GitAnalyzer');

async function analyzeChanges(projectPath: string) {
  const { diff, files, hasChanges } = await getGitRepositoryDiffs(projectPath);

  if (!hasChanges) {
    logger.info('No changes detected');
    return;
  }

  // Group by status
  const modified = files.filter(f => f.status === 'M');
  const added = files.filter(f => f.status === 'A');
  const deleted = files.filter(f => f.status === 'D');
  const untracked = files.filter(f => f.status === '?');

  logger.info(`Changes: ${modified.length}M ${added.length}A ${deleted.length}D ${untracked.length}U`);

  return diff;
}

Ordering Features for Execution

import type { Feature } from '@automaker/types';
import { resolveDependencies, getBlockingDependencies } from '@automaker/dependency-resolver';
import { createLogger } from '@automaker/utils';

const logger = createLogger('FeatureOrdering');

function orderAndFilterFeatures(features: Feature[]): Feature[] {
  const { orderedFeatures, hasCycle, cyclicFeatures } = resolveDependencies(features);

  if (hasCycle) {
    logger.error(`Circular dependency detected: ${cyclicFeatures.join(' → ')}`);
    throw new Error('Cannot execute features with circular dependencies');
  }

  // Filter to only ready features
  const readyFeatures = orderedFeatures.filter(feature => {
    const blocking = getBlockingDependencies(feature, features);
    if (blocking.length > 0) {
      logger.debug(`${feature.id} blocked by: ${blocking.join(', ')}`);
      return false;
    }
    return true;
  });

  logger.info(`${readyFeatures.length} of ${features.length} features ready`);
  return readyFeatures;
}

Import Rules for LLMs

DO

// Import types from @automaker/types
import type { Feature, ExecuteOptions } from '@automaker/types';

// Import constants from @automaker/types
import { CLAUDE_MODEL_MAP, DEFAULT_MODELS } from '@automaker/types';

// Import utilities from @automaker/utils
import { createLogger, classifyError } from '@automaker/utils';

// Import platform utils from @automaker/platform
import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform';

// Import model resolution from @automaker/model-resolver
import { resolveModelString } from '@automaker/model-resolver';

// Import dependency resolution from @automaker/dependency-resolver
import { resolveDependencies } from '@automaker/dependency-resolver';

// Import git utils from @automaker/git-utils
import { getGitRepositoryDiffs } from '@automaker/git-utils';

DON'T

// DON'T import from old paths
import { Feature } from '../services/feature-loader';           // ❌
import { ExecuteOptions } from '../providers/types';            // ❌
import { createLogger } from '../lib/logger';                   // ❌
import { resolveModelString } from '../lib/model-resolver';     // ❌
import { isGitRepo } from '../routes/common';                   // ❌
import { resolveDependencies } from '../lib/dependency-resolver'; // ❌

// DON'T import from old lib/ paths
import { getFeatureDir } from '../lib/automaker-paths';         // ❌
import { classifyError } from '../lib/error-handler';           // ❌

// DON'T define types that exist in @automaker/types
interface Feature { ... }  // ❌ Use: import type { Feature } from '@automaker/types';

Migration Checklist

When refactoring server code, check:

  • All Feature imports use @automaker/types
  • All ExecuteOptions imports use @automaker/types
  • All logger usage uses @automaker/utils
  • All path operations use @automaker/platform
  • All model resolution uses @automaker/model-resolver
  • All dependency checks use @automaker/dependency-resolver
  • All git operations use @automaker/git-utils
  • No imports from old lib/ paths
  • No imports from services/feature-loader for types
  • No imports from providers/types

Package Dependencies

Understanding the dependency chain helps prevent circular dependencies:

@automaker/types (no dependencies)
    ↓
@automaker/utils
@automaker/platform
@automaker/model-resolver
@automaker/dependency-resolver
    ↓
@automaker/git-utils
    ↓
@automaker/server
@automaker/ui

Rule: Packages can only depend on packages above them in the chain.

Building Packages

All packages must be built before use:

# Build all packages
cd libs/types && npm run build
cd libs/utils && npm run build
cd libs/platform && npm run build
cd libs/model-resolver && npm run build
cd libs/dependency-resolver && npm run build
cd libs/git-utils && npm run build

# Or from root
npm install  # Installs and links workspace packages

Module Format

  • dependency-resolver: ES modules (type: "module") for Vite compatibility
  • All others: CommonJS for Node.js compatibility

Testing

When writing tests:

// ✅ Import from packages
import type { Feature } from '@automaker/types';
import { createLogger } from '@automaker/utils';

// ❌ Don't import from src
import { Feature } from '../../../src/services/feature-loader';

Summary for LLMs

Quick reference:

  • Types → @automaker/types
  • Logging/Errors → @automaker/utils
  • Paths/Security → @automaker/platform
  • Model Resolution → @automaker/model-resolver
  • Dependency Ordering → @automaker/dependency-resolver
  • Git Operations → @automaker/git-utils

Never import from: lib/*, services/feature-loader (for types), providers/types, routes/common

Always: Use the shared packages instead of local implementations.