# Configuration Access Guidelines

This note summarizes how to use `ConfigManager` after the October 2025 refactor.  
All direct access to environment variables (`os.getenv`, `os.environ[...]`, etc.) should now flow through the manager.

## Core API

- `ConfigManager.get(key, default=None, cast=None, allow_empty=True)`  
  Looks up a value in the following order: runtime overrides → environment variables → `AppConfig` fields → `default`.  
  When `cast` is provided (e.g. `int`, `Path`, or a custom callable), the value is converted; conversion errors fall back to `default`.  
  Set `allow_empty=False` to treat empty strings as missing.

- `ConfigManager.get_bool(key, default=False)`  
  Convenience helper for booleans. Recognises `1/true/yes/on` and `0/false/no/off`. Invalid strings log a warning and return `default`.

- `ConfigManager.set(key, value, persist_env=True)`  
  Registers a runtime override and, when `persist_env=True`, updates `os.environ`. Passing `value=None` removes the corresponding environment variable. When a matching `AppConfig` field exists, the value is cast to the field type automatically.
- `ConfigManager.require(key)`  
  Fetches a mandatory value. Raises `KeyError` when the key is missing—use this when replacing `os.environ["NAME"]` so failure semantics stay identical.

## Best Practices

1. **Do not call `os.getenv` / `os.environ` directly.** Replace legacy reads with `config.get(...)` or `config.get_bool(...)`.
2. **Prefer the helpers for type safety.** Use `cast=` for numeric/path values and `get_bool` for flags.
3. **Use `set(..., persist_env=False)` inside tests.** This prevents test runs from leaking state into the real environment.
4. **Document new keys.** Whenever a new configuration key is introduced, update this file (or the relevant domain documentation) so the contract remains visible.

## Migration Tips

When refactoring legacy code manually:

- Search for `os.getenv`, `os.environ.get`, and `os.environ[...]`.
- Replace reads with `config = get_config_manager()` (or the local equivalent) followed by `config.get(...)` / `config.get_bool(...)`.
- Replace writes with `config.set(...)`, considering whether the change should persist to `os.environ`.
- Run the targeted tests for the affected module after each batch of replacements.

## Automation

- Preview replacements: `python -S scripts/refactor/migrate_os_getenv.py --quiet src/noveler/...`  
  Review the diff, then apply with `--apply` once satisfied (apply mode is blocked in CI).
- Regenerate the usage report: `python -S scripts/refactor/report_os_env_usage.py`  
  The CSV at `reports/conf_phase1_os_env_targets.csv` is the authoritative list of remaining direct environment accesses.

## Checklist

- [ ] All environment access in the module goes through `ConfigManager`.
- [ ] Boolean flags use `get_bool` (or equivalent helper) instead of string comparisons.
- [ ] Calls to `set` evaluate whether `persist_env` should be `True` or `False`.
- [ ] New keys are documented and exercised by unit tests.

## References

- Implementation: `src/noveler/infrastructure/config/config_manager.py`
- Tests: `tests/unit/infrastructure/test_config_manager.py`
- Historical context: `reports/LEGACY_CODE_ANALYSIS_2025_10_24.md`
