Skip to content

feat: add env var substitution and config file discovery to loader #76

@Aureliolo

Description

@Aureliolo

Context

PR #75 implements the core YAML config loader with layered merging and Pydantic validation. Two acceptance criteria from #59 were deferred to keep the PR focused:

  1. Environment variable substitution${ENV_VAR} placeholders in config values should be expanded before validation
  2. Config file discoveryload_config() should search standard locations (./, ~/.ai-company/, etc.) when no explicit path is given

Acceptance Criteria

  • ${ENV_VAR} syntax in any string value is replaced with the environment variable's value before Pydantic validation
  • Missing env vars raise ConfigValidationError with a clear message naming the variable
  • Optional default syntax ${ENV_VAR:-default} is supported
  • discover_config() searches: ./ai-company.yaml, ./config/ai-company.yaml, ~/.ai-company/config.yaml (in order)
  • load_config() accepts config_path=None and falls back to discovery
  • ConfigFileNotFoundError raised when no config found in any location
  • Unit tests for: substitution (present/missing/default), discovery (each location, precedence, not found)

Design Spec Reference

Sections 4.3, 5.4

Notes

  • Keep load_config(config_path: Path | str) signature backward-compatible — make config_path optional with None default
  • Env var expansion should happen on the merged dict (after deep merge, before Pydantic validation)
  • Use re.sub with os.environ.get() for substitution — no need for a templating library

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:mediumShould do, but not blockingscope:medium1-3 days of workspec:architectureDESIGN_SPEC Section 15 - Technical Architecturetype:featureNew feature implementationtype:testTest coverage, test infrastructure

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions