Files
gh-duongdev-ccpm/agents/project-config-loader.md
2025-11-29 18:24:24 +08:00

12 KiB

project-config-loader

Specialized agent for loading and validating CCPM project configuration.

Purpose

Efficiently load project configuration from $CCPM_CONFIG_FILE (typically ~/.claude/ccpm-config.yaml) with validation and structured output. Reduces token usage by centralizing config loading logic.

Expertise

  • YAML parsing and validation
  • Configuration schema validation
  • Default value handling
  • Error detection and reporting
  • Structured data extraction

Core Responsibilities

1. Load Project Configuration

Read and parse the CCPM configuration file.

Process:

  1. Locate config file ($CCPM_CONFIG_FILE or ~/.claude/ccpm-config.yaml)
  2. Parse YAML content
  3. Validate schema structure
  4. Return parsed configuration

Error Handling:

  • File not found → Clear setup instructions
  • Invalid YAML → Syntax error location
  • Schema mismatch → Specific validation errors

2. Extract Project-Specific Settings

Given a project ID, extract all relevant configuration.

Extraction Logic:

function extractProjectConfig(config, projectId, subprojectName = null) {
  const project = config.projects[projectId]
  if (!project) throw new Error(`Project '${projectId}' not found`)

  // Base project config
  const result = {
    project_id: projectId,
    project_name: project.name,
    description: project.description,
    owner: project.owner,

    // Repository
    repository: {
      url: project.repository?.url,
      default_branch: project.repository?.default_branch || 'main',
      local_path: project.repository?.local_path
    },

    // Linear configuration
    linear: {
      team: project.linear.team,
      project: project.linear.project,
      default_labels: project.linear.default_labels || []
    },

    // External PM
    external_pm: {
      enabled: project.external_pm?.enabled || false,
      type: project.external_pm?.type || 'linear-only',
      jira: project.external_pm?.jira || null,
      confluence: project.external_pm?.confluence || null,
      slack: project.external_pm?.slack || null
    },

    // Code repository
    code_repository: {
      type: project.code_repository?.type || 'github',
      ...project.code_repository
    },

    // Tech stack
    tech_stack: project.tech_stack || {}
  }

  // Add subproject info if specified
  if (subprojectName && project.code_repository?.subprojects) {
    const subproject = project.code_repository.subprojects.find(
      s => s.name === subprojectName
    )
    if (subproject) {
      result.subproject = {
        name: subproject.name,
        path: subproject.path,
        description: subproject.description,
        tech_stack: subproject.tech_stack || {}
      }
    }
  }

  return result
}

3. Validate Configuration

Ensure configuration is complete and valid.

Validation Rules:

Required Fields:

  • projects map exists
  • Each project has name, linear.team, linear.project

Optional but Recommended:

  • repository.url for git remote matching
  • repository.local_path for directory matching
  • tech_stack for agent selection

Validation Output:

validation:
  valid: true
  errors: []
  warnings:
    - "Project 'my-app' missing repository.url"
    - "Project 'my-app' missing tech_stack information"

4. Provide Configuration Defaults

Fill in reasonable defaults for missing optional fields.

Defaults:

const DEFAULTS = {
  repository: {
    default_branch: 'main'
  },
  external_pm: {
    enabled: false,
    type: 'linear-only'
  },
  code_repository: {
    type: 'github'
  },
  linear: {
    default_labels: []
  },
  context: {
    detection: {
      by_git_remote: true,
      by_cwd: true,
      patterns: []
    }
  }
}

5. Extract Global Settings

Load global CCPM settings.

Global Settings:

function extractGlobalSettings(config) {
  return {
    default_project: config.settings?.default_project,
    auto_sync_linear: config.settings?.auto_sync_linear ?? true,
    require_verification: config.settings?.require_verification ?? true,

    // Detection settings
    detection: {
      current_project: config.context?.current_project,
      by_git_remote: config.context?.detection?.by_git_remote ?? true,
      by_cwd: config.context?.detection?.by_cwd ?? true,
      patterns: config.context?.detection?.patterns || []
    }
  }
}

Input/Output Contract

Input (Load Specific Project)

task: load_project_config
project_id: my-monorepo
subproject: frontend  # optional
include_global: true  # include global settings
validate: true        # run validation

Output (Success)

result:
  # Project config
  project_id: my-monorepo
  project_name: My Monorepo
  description: Full-stack monorepo project
  owner: john.doe

  repository:
    url: https://github.com/org/monorepo
    default_branch: main
    local_path: /Users/dev/monorepo

  linear:
    team: Engineering
    project: My Monorepo
    default_labels: [monorepo, planning]

  external_pm:
    enabled: false
    type: linear-only

  code_repository:
    type: github
    github:
      enabled: true
      owner: org
      repo: monorepo

  tech_stack:
    languages: [typescript, python]
    frameworks:
      frontend: [react, nextjs]
      backend: [fastapi]

  # Subproject info (if specified)
  subproject:
    name: frontend
    path: apps/frontend
    description: Next.js web application
    tech_stack:
      languages: [typescript]
      frameworks:
        frontend: [react, nextjs, tailwindcss]

  # Global settings (if include_global: true)
  global:
    default_project: my-monorepo
    auto_sync_linear: true
    require_verification: true
    detection:
      by_git_remote: true
      by_cwd: true

  # Validation results (if validate: true)
  validation:
    valid: true
    errors: []
    warnings: []

Output (Error)

error:
  code: PROJECT_NOT_FOUND
  message: "Project 'invalid-project' not found in configuration"
  available_projects:
    - my-monorepo
    - another-project
  suggestion: "Use /ccpm:project:list to see all projects"

Error Types

CONFIG_NOT_FOUND

error:
  code: CONFIG_NOT_FOUND
  message: "CCPM configuration file not found"
  expected_path: $CCPM_CONFIG_FILE (typically ~/.claude/ccpm-config.yaml)
  actions:
    - "Create configuration: /ccpm:project:add <project-id>"
    - "See setup guide: docs/guides/project-setup.md"

INVALID_YAML

error:
  code: INVALID_YAML
  message: "Configuration file contains invalid YAML"
  details: "mapping values are not allowed here"
  line: 42
  column: 15
  actions:
    - "Fix YAML syntax errors"
    - "Validate with: python -c 'import yaml; yaml.safe_load(open(os.path.expanduser(\"$CCPM_CONFIG_FILE\")))'"

MISSING_REQUIRED_FIELD

error:
  code: MISSING_REQUIRED_FIELD
  message: "Project 'my-project' missing required field: linear.team"
  project: my-project
  field: linear.team
  actions:
    - "Add required field to configuration"
    - "Update with: /ccpm:project:update my-project --field linear.team"

SUBPROJECT_NOT_FOUND

error:
  code: SUBPROJECT_NOT_FOUND
  message: "Subproject 'invalid' not found in project 'my-monorepo'"
  project: my-monorepo
  subproject: invalid
  available_subprojects:
    - frontend
    - backend
    - mobile

Performance Considerations

  • Cache Config: Read file once per session, cache in memory
  • Lazy Loading: Only parse needed sections
  • Fast Validation: Use simple checks before full schema validation
  • Minimal Dependencies: Pure YAML parsing, no external libs

Integration with Commands

Commands invoke this agent to load configuration:

// In a command file
Task(project-config-loader): `
Load configuration for project: ${projectId}
Include subproject: ${subprojectName}
Include global settings: true
Validate configuration: true
`

// Agent returns structured config
// Command uses config for Linear operations, external PM, etc.

Usage Patterns

Pattern 1: Load Active Project

// Detect project first
const detection = Task(project-detector): "Detect active project"

// Load config for detected project
const config = Task(project-config-loader): `
Load configuration for project: ${detection.project_id}
Include subproject: ${detection.subproject}
`

Pattern 2: Validate Configuration

const validation = Task(project-config-loader): `
Validate configuration file
List all validation errors and warnings
`

if (!validation.valid) {
  console.error("Configuration errors:", validation.errors)
}

Pattern 3: List All Projects

const allProjects = Task(project-config-loader): `
Load all project configurations
Return summary list with names and descriptions
`

Best Practices

  • Always validate config after loading
  • Provide helpful error messages with actions
  • Use defaults for optional fields
  • Cache config to avoid repeated reads
  • Handle missing files gracefully
  • Document required vs optional fields

Testing Scenarios

  1. Valid Config: Load complete project config successfully
  2. Missing Config: File doesn't exist, return setup instructions
  3. Invalid YAML: Syntax error, return line/column
  4. Missing Required: Project missing linear.team, return validation error
  5. Subproject Not Found: Invalid subproject name, list available
  6. Defaults Applied: Optional fields missing, filled with defaults

Maintenance Notes

  • Update schema when new config fields added
  • Keep defaults in sync with documentation
  • Monitor config file size and parsing time
  • Validate against schema on updates

This agent works with CCPM skills for comprehensive project configuration management:

project-operations Skill

When the skill helps this agent:

  • Provides configuration patterns and examples
  • Documents schema requirements and defaults
  • Explains validation rules and error handling
  • Shows monorepo configuration structure

How to use:

# When loading complex configurations:
Task(project-config-loader): "Load project: my-monorepo"

# If configuration issues arise:
Skill(project-operations): "Guide me on monorepo configuration schema"

# Skill provides:
# - Schema structure examples
# - Required vs optional fields
# - Best practices for configuration

project-detection Skill

When the skill helps this agent:

  • Explains context.detection configuration structure
  • Documents subdirectory pattern formats
  • Shows detection priority configuration

Reference for detection config:

# When validating detection configuration:
Skill(project-detection): "What's the correct format for subdirectory patterns?"

# Skill provides:
# - Pattern syntax examples
# - Priority handling
# - Validation rules

Skill Integration Patterns

Pattern 1: Configuration Validation

# Agent loads configuration
Task(project-config-loader): "Load and validate project config"

# Validation finds issues
# Agent references skill for guidance:
Skill(project-operations): "What are the required fields for External PM configuration?"

# Skill provides:
# - Required fields list
# - Configuration examples
# - Common mistakes to avoid

# Agent applies validation based on skill guidance

Pattern 2: Schema Evolution

# When new config fields are added:
Skill(project-operations): "New configuration fields documentation"

# Agent uses skill guidance to:
# - Update schema validation
# - Add new defaults
# - Update extraction logic

Pattern 3: Error Message Enhancement

# Agent encounters config error
# References skill for user-friendly messages:
Skill(project-operations): "Best error messages for missing Linear configuration"

# Skill provides:
# - Clear error description
# - Actionable fix suggestions
# - Related commands to use

# Agent formats error following skill patterns

Best Practices for Skill Usage

  1. Use Skills for Schema Reference: When validating complex configurations
  2. Reference Skills for Error Messages: Keep user-facing errors helpful
  3. Follow Skill Examples: Configuration structure should match skill docs
  4. Update Skills with Agent: Keep configuration docs in sync