# Story 10.8: Smart Environment Auto-Detection

## Status: Planned

## Priority: High

## Estimated Effort: Medium (2-3 days)

## Dependencies

- **Depends on:** Story 10.1 (Configuration Presets) - Uses preset system
- **Depends on:** Story 10.6 (Enhanced Default Behaviors) - Uses default selection helpers (is_ci_environment, is_tty_environment)
- **Depends on:** Story 10.2 (Pretty Console Output) - Uses format detection

## Epic / Series

Part of Epic 10: Developer Experience and Ergonomics / Series 10.x

---

## Context / Background

Default behavior should adapt to deployment context. This story provides **comprehensive environment auto-detection** that automatically configures the logger for local, Docker, Kubernetes, Lambda, and CI environments without manual setup.

**Relationship to Story 10.6:**
- Story 10.6 provides **simple defaults** (log level based on TTY/CI, sink fallback)
- Story 10.8 provides **full environment detection** (Docker, Kubernetes, Lambda) and auto-configuration
- Story 10.8 uses helpers from Story 10.6 (`is_ci_environment()`, `is_tty_environment()`)
- Story 10.8 auto-enables enrichers based on detected environment

## Scope (In / Out)

### In Scope

- **Environment detection**: Local, Docker, Kubernetes, AWS Lambda, CI environments
- **Auto-configuration**: Apply environment-specific presets and settings
- **Auto-enable enrichers**: Automatically enable Kubernetes/Docker enrichers when detected
- **Opt-out mechanism**: Allow disabling auto-detection
- **Explicit overrides**: Allow manual environment specification

### Out of Scope

- **Simple defaults** (TTY/CI log level, sink fallback) - See Story 10.6
- **Output format detection** - Already implemented in Story 10.2
- **Deep platform integrations** beyond metadata enrichment
- **External service calls** during detection
- **Custom environment types** (users can use presets for custom environments)

## Acceptance Criteria

### AC1: Environment Detection

**`detect_environment()` identifies deployment contexts:**

```python
from fapilog.core.environment import detect_environment

# Detection methods:
environment = detect_environment()
# Returns: "local" | "docker" | "kubernetes" | "lambda" | "ci"
```

**Detection logic (priority order):**

1. **Lambda**: `AWS_LAMBDA_FUNCTION_NAME` env var present
2. **Kubernetes**: `/var/run/secrets/kubernetes.io/serviceaccount` exists OR `POD_NAME` env var present
3. **Docker**: `/proc/1/cgroup` contains "docker" OR `/.dockerenv` exists
4. **CI**: Uses `is_ci_environment()` from Story 10.6
5. **Local**: Default if none of above match

**Detection is cached** (per-process) to avoid repeated filesystem checks.

### AC2: Auto-Configuration Per Environment

**Auto-detected configuration applies per environment:**

```python
# Lambda environment
logger = get_logger()  # Auto-detected
# Applied: INFO level, JSON format, optimized batching, Lambda enricher

# Kubernetes environment
logger = get_logger()  # Auto-detected
# Applied: INFO level, JSON format, Kubernetes enricher enabled

# Docker environment
logger = get_logger()  # Auto-detected
# Applied: INFO level, JSON format, container metadata

# Local environment
logger = get_logger()  # Auto-detected
# Applied: Uses Story 10.6 defaults (DEBUG if TTY, INFO otherwise)
```

**Environment-specific configurations:**

| Environment | Log Level | Format | Enrichers | Notes |
|------------|-----------|--------|-----------|-------|
| **Lambda** | INFO | JSON | `runtime_info` | Optimized batching; Lambda enricher not yet implemented |
| **Kubernetes** | INFO | JSON | `runtime_info`, `kubernetes` | Kubernetes enricher auto-enabled |
| **Docker** | INFO | JSON | `runtime_info` | Container metadata via runtime_info |
| **CI** | INFO | JSON | `runtime_info` | Uses Story 10.6 detection |
| **Local** | DEBUG (TTY) / INFO | auto | `runtime_info` | Uses Story 10.6 defaults |

### AC3: Auto-Enable Enrichers

**Enrichers automatically enabled based on environment:**

```python
# Kubernetes detected
logger = get_logger()
# KubernetesEnricher automatically added to enrichers list
# Logs include: k8s_pod, k8s_namespace, k8s_node, etc.

# Docker detected
logger = get_logger()
# Container metadata added via runtime_info enricher
# Logs include: container_id (if available)
```

**Auto-enabling logic:**
- Kubernetes: Enable `kubernetes` enricher (reads from env vars: POD_NAME, POD_NAMESPACE, etc.)
- Docker: Container metadata via `runtime_info` enricher (no special enricher needed)
- Lambda: Use `runtime_info` enricher (Lambda-specific enricher not yet implemented)
- CI: Standard `runtime_info` enricher
- Local: Standard `runtime_info` enricher

**Note**: `KubernetesEnricher` already exists and is ready to use. It reads from standard Kubernetes environment variables (Downward API) and requires no API calls or volume mounts.

### AC4: Opt-Out and Overrides

**Disable auto-detection:**

```python
# Disable auto-detection
logger = get_logger(auto_detect=False)
# Uses Story 10.6 defaults only (no environment detection)

# Explicit environment override
logger = get_logger(environment="production")
# Uses production preset, ignores auto-detection
```

**Priority order:**
1. Explicit `environment` parameter
2. Explicit `preset` parameter
3. Explicit `settings` parameter
4. Auto-detection (if enabled)
5. Story 10.6 defaults

### AC5: Lambda-Specific Optimizations

**Lambda environment gets optimized settings:**

```python
# Lambda detected
logger = get_logger()
# Applied settings:
# - batch_max_size: 10 (smaller batches for Lambda timeouts)
# - batch_timeout_seconds: 0.1 (faster flushing)
# - max_queue_size: 1000 (smaller queue for Lambda memory)
# - format: "json" (structured logs for CloudWatch)
```

**Rationale**: Lambda has strict timeouts and memory limits, so batching is optimized for quick flushes. JSON format ensures logs are properly structured for CloudWatch ingestion.

### AC6: Kubernetes Metadata Enrichment

**Kubernetes enricher automatically enabled and configured:**

```python
# Kubernetes detected
logger = get_logger()
# KubernetesEnricher enabled with default config
# Reads from standard env vars:
# - POD_NAME
# - POD_NAMESPACE
# - NODE_NAME
# - CONTAINER_NAME
# - CLUSTER_NAME
```

**Note**: KubernetesEnricher already exists - this story just auto-enables it.

### AC7: Docker Metadata Detection

**Docker environment detected and container metadata added:**

```python
# Docker detected
logger = get_logger()
# Container metadata available via runtime_info enricher
# Logs include container context when available
```

**Detection methods:**
- Check `/proc/1/cgroup` for "docker" (most reliable)
- Check for `/.dockerenv` file (Docker creates this file)
- Note: Docker detection may also match in Kubernetes pods (which run in containers), but Kubernetes detection takes priority

### AC8: Tests Validate Detection and Configuration

- Test: Each environment detected correctly
- Test: Auto-configuration applied per environment
- Test: Enrichers auto-enabled based on environment
- Test: Opt-out disables auto-detection
- Test: Explicit overrides take precedence
- Test: Lambda optimizations applied
- Test: Detection is cached (not repeated)

## Implementation Notes

### File Structure

```
src/fapilog/core/environment.py (NEW)
  - detect_environment()
  - get_environment_config()
  - _detect_lambda()
  - _detect_kubernetes()
  - _detect_docker()
  - _detect_ci()  # Uses Story 10.6 helper

src/fapilog/__init__.py (MODIFIED)
  - Add auto_detect parameter to get_logger() / get_async_logger()
  - Add environment parameter to get_logger() / get_async_logger()
  - Integrate environment detection into logger creation

tests/unit/test_environment_detection.py (NEW)
tests/integration/test_auto_config.py (NEW)
```

### Implementation Approach

**1. Environment Detection:**

```python
# src/fapilog/core/environment.py
from typing import Literal
import os
from pathlib import Path

EnvironmentType = Literal["local", "docker", "kubernetes", "lambda", "ci"]

_ENV_CACHE: EnvironmentType | None = None

def detect_environment(*, use_cache: bool = True) -> EnvironmentType:
    """Detect deployment environment.
    
    Priority order:
    1. Lambda (AWS_LAMBDA_FUNCTION_NAME)
    2. Kubernetes (serviceaccount path or POD_NAME)
    3. Docker (/proc/1/cgroup or /.dockerenv)
    4. CI (uses Story 10.6 helper)
    5. Local (default)
    
    Args:
        use_cache: Use cached result if available (default True)
    
    Returns:
        Detected environment type
    """
    global _ENV_CACHE
    if use_cache and _ENV_CACHE is not None:
        return _ENV_CACHE
    
    # Lambda detection (highest priority - Lambda can run in containers)
    if os.getenv("AWS_LAMBDA_FUNCTION_NAME"):
        _ENV_CACHE = "lambda"
        return "lambda"
    
    # Kubernetes detection
    if _detect_kubernetes():
        _ENV_CACHE = "kubernetes"
        return "kubernetes"
    
    # Docker detection
    if _detect_docker():
        _ENV_CACHE = "docker"
        return "docker"
    
    # CI detection (uses Story 10.6 helper)
    from .defaults import is_ci_environment
    if is_ci_environment():
        _ENV_CACHE = "ci"
        return "ci"
    
    # Local (default)
    _ENV_CACHE = "local"
    return "local"

def _detect_kubernetes() -> bool:
    """Detect Kubernetes environment.
    
    Uses two methods:
    1. Service account path (most reliable - only exists in K8s pods)
    2. POD_NAME env var (common in K8s deployments via Downward API)
    
    Note: POD_NAME alone is not definitive (could be set manually), but
    combined with serviceaccount path check, provides good coverage.
    """
    # Method 1: Service account path (most reliable)
    if Path("/var/run/secrets/kubernetes.io/serviceaccount").exists():
        return True
    
    # Method 2: POD_NAME env var (common in K8s via Downward API)
    if os.getenv("POD_NAME"):
        return True
    
    return False

def _detect_docker() -> bool:
    """Detect Docker environment.
    
    Uses two methods:
    1. /.dockerenv file (Docker creates this file in containers)
    2. /proc/1/cgroup contains "docker" (checks cgroup hierarchy)
    
    Note: This may also match in Kubernetes pods (which run in containers),
    but Kubernetes detection takes priority in detect_environment().
    """
    # Method 1: /.dockerenv file (Docker-specific)
    if Path("/.dockerenv").exists():
        return True
    
    # Method 2: /proc/1/cgroup contains "docker"
    try:
        cgroup_path = Path("/proc/1/cgroup")
        if cgroup_path.exists():
            content = cgroup_path.read_text()
            if "docker" in content.lower():
                return True
    except (OSError, PermissionError, UnicodeDecodeError):
        # Handle cases where file doesn't exist, can't be read, or contains binary data
        pass
    
    return False
```

**2. Environment-Specific Configuration:**

```python
def get_environment_config(env: EnvironmentType) -> dict[str, Any]:
    """Get configuration for detected environment.
    
    Returns Settings-compatible dict that can be merged with presets.
    """
    configs = {
        "lambda": {
            "core": {
                "log_level": "INFO",
                "batch_max_size": 10,
                "batch_timeout_seconds": 0.1,
                "max_queue_size": 1000,
            },
            "enrichers": ["runtime_info"],  # Lambda-specific enricher not yet implemented
        },
        "kubernetes": {
            "core": {
                "log_level": "INFO",
            },
            "enrichers": ["runtime_info", "kubernetes"],  # Auto-enable
        },
        "docker": {
            "core": {
                "log_level": "INFO",
            },
            "enrichers": ["runtime_info"],  # Container metadata via runtime_info
        },
        "ci": {
            "core": {
                "log_level": "INFO",  # Uses Story 10.6 helper
            },
            "enrichers": ["runtime_info"],
        },
        "local": {
            # Uses Story 10.6 defaults (no override)
            "enrichers": ["runtime_info"],
        },
    }
    return configs.get(env, {})
```

**3. Integration with Logger Creation:**

```python
# In get_logger() / get_async_logger()
def get_logger(
    *,
    auto_detect: bool = True,
    environment: str | None = None,
    preset: str | None = None,
    format: str | None = None,
    settings: _Settings | None = None,
    ...
):
    """
    Priority order (highest to lowest):
    1. Explicit settings parameter (no auto-detection)
    2. Explicit preset parameter (no auto-detection)
    3. Explicit environment parameter (manual override)
    4. Auto-detection (if auto_detect=True)
    5. Story 10.6 defaults (TTY/CI detection, sink fallback)
    """
    # Priority 1: Explicit settings - no auto-detection
    if settings is not None:
        # Use settings as-is, no environment detection
        ...
    
    # Priority 2: Explicit preset - no auto-detection
    elif preset is not None:
        # Apply preset, no environment detection
        ...
    
    # Priority 3: Explicit environment override
    elif environment is not None:
        # Use specified environment config
        env_config = get_environment_config(environment)
        # Merge with Story 10.6 defaults
        settings = _merge_config(env_config, _get_default_config())
        ...
    
    # Priority 4: Auto-detect environment
    elif auto_detect:
        # Auto-detect environment
        detected = detect_environment()
        env_config = get_environment_config(detected)
        # Merge with Story 10.6 defaults
        settings = _merge_config(env_config, _get_default_config())
        ...
    
    # Priority 5: No auto-detection - use Story 10.6 defaults only
    else:
        # Use Story 10.6 defaults (TTY/CI detection, sink fallback)
        settings = _get_default_config()
        ...
```

**Assumption**: Explicit settings/preset/environment always override auto-detection. Auto-detection only runs when no explicit configuration is provided.

## Tasks

### Phase 1: Environment Detection

- [ ] Create `src/fapilog/core/environment.py`
- [ ] Implement `detect_environment()` function
- [ ] Implement `_detect_lambda()` (AWS_LAMBDA_FUNCTION_NAME)
- [ ] Implement `_detect_kubernetes()` (serviceaccount path, POD_NAME)
- [ ] Implement `_detect_docker()` (/.dockerenv, /proc/1/cgroup)
- [ ] Use `is_ci_environment()` from Story 10.6 for CI detection
- [ ] Implement detection caching (per-process)
- [ ] Export from `src/fapilog/core/__init__.py`

### Phase 2: Environment Configuration

- [ ] Implement `get_environment_config()` function
- [ ] Define Lambda configuration (optimized batching)
- [ ] Define Kubernetes configuration (auto-enable enricher)
- [ ] Define Docker configuration
- [ ] Define CI configuration (uses Story 10.6 defaults)
- [ ] Define Local configuration (uses Story 10.6 defaults)

### Phase 3: Logger Integration

- [ ] Add `auto_detect` parameter to `get_logger()`
- [ ] Add `auto_detect` parameter to `get_async_logger()`
- [ ] Add `environment` parameter to `get_logger()`
- [ ] Add `environment` parameter to `get_async_logger()`
- [ ] Integrate environment detection into logger creation
- [ ] Ensure priority: explicit > preset > auto-detect > defaults
- [ ] Auto-enable enrichers based on environment

### Phase 4: Enricher Auto-Enable

- [ ] Auto-enable `kubernetes` enricher for Kubernetes environment
- [ ] Ensure `runtime_info` enricher enabled for all environments
- [ ] Test enricher configuration per environment
- [ ] Note: Lambda-specific enricher not yet implemented (use runtime_info for now)

### Phase 5: Testing

- [ ] Create `tests/unit/test_environment_detection.py`
- [ ] Test Lambda detection (AWS_LAMBDA_FUNCTION_NAME)
- [ ] Test Kubernetes detection (serviceaccount path, POD_NAME)
- [ ] Test Docker detection (/.dockerenv, /proc/1/cgroup)
- [ ] Test CI detection (uses Story 10.6 helper)
- [ ] Test Local detection (default)
- [ ] Test detection caching
- [ ] Create `tests/integration/test_auto_config.py`
- [ ] Test auto-configuration per environment
- [ ] Test enricher auto-enabling
- [ ] Test opt-out mechanism
- [ ] Test explicit overrides

### Phase 6: Documentation

- [ ] Update `docs/user-guide/configuration.md` with auto-detection
- [ ] Document environment detection methods
- [ ] Document environment-specific configurations
- [ ] Document opt-out and override mechanisms
- [ ] Add examples for each environment
- [ ] Update `CHANGELOG.md`

## Tests

### Unit Tests (`tests/unit/test_environment_detection.py`)

```python
"""Unit tests for environment detection."""

import os
from pathlib import Path
from unittest.mock import patch

import pytest

from fapilog.core.environment import (
    detect_environment,
    _detect_docker,
    _detect_kubernetes,
    _detect_lambda,
)


class TestDetectLambda:
    """Test Lambda environment detection."""

    def test_lambda_detected(self):
        """Lambda detected via AWS_LAMBDA_FUNCTION_NAME."""
        with patch.dict(os.environ, {"AWS_LAMBDA_FUNCTION_NAME": "my-function"}):
            assert _detect_lambda() is True

    def test_no_lambda_env_var(self):
        """No Lambda env var returns False."""
        with patch.dict(os.environ, {}, clear=True):
            assert _detect_lambda() is False


class TestDetectKubernetes:
    """Test Kubernetes environment detection."""

    def test_k8s_detected_via_serviceaccount(self, tmp_path):
        """Kubernetes detected via serviceaccount path."""
        sa_path = tmp_path / "var/run/secrets/kubernetes.io/serviceaccount"
        sa_path.parent.mkdir(parents=True, exist_ok=True)
        sa_path.touch()
        
        with patch("fapilog.core.environment.Path", return_value=sa_path):
            assert _detect_kubernetes() is True

    def test_k8s_detected_via_pod_name(self):
        """Kubernetes detected via POD_NAME env var."""
        with patch.dict(os.environ, {"POD_NAME": "my-pod-123"}):
            assert _detect_kubernetes() is True

    def test_no_k8s_indicators(self):
        """No Kubernetes indicators returns False."""
        with patch.dict(os.environ, {}, clear=True):
            with patch("pathlib.Path.exists", return_value=False):
                assert _detect_kubernetes() is False


class TestDetectDocker:
    """Test Docker environment detection."""

    def test_docker_detected_via_dockerenv(self, tmp_path):
        """Docker detected via /.dockerenv file."""
        dockerenv = tmp_path / ".dockerenv"
        dockerenv.touch()
        
        with patch("fapilog.core.environment.Path", return_value=dockerenv):
            assert _detect_docker() is True

    def test_docker_detected_via_cgroup(self, tmp_path):
        """Docker detected via /proc/1/cgroup."""
        cgroup = tmp_path / "proc/1/cgroup"
        cgroup.parent.mkdir(parents=True, exist_ok=True)
        cgroup.write_text("1:name=systemd:/docker/abc123")
        
        with patch("fapilog.core.environment.Path", return_value=cgroup):
            assert _detect_docker() is True

    def test_no_docker_indicators(self):
        """No Docker indicators returns False."""
        with patch("pathlib.Path.exists", return_value=False):
            assert _detect_docker() is False


class TestDetectEnvironment:
    """Test full environment detection."""

    def test_priority_lambda_first(self):
        """Lambda takes priority over other environments."""
        with patch.dict(os.environ, {
            "AWS_LAMBDA_FUNCTION_NAME": "func",
            "POD_NAME": "pod",
        }):
            assert detect_environment(use_cache=False) == "lambda"

    def test_priority_k8s_before_docker(self):
        """Kubernetes takes priority over Docker."""
        with patch.dict(os.environ, {"POD_NAME": "pod"}):
            with patch("fapilog.core.environment._detect_docker", return_value=True):
                assert detect_environment(use_cache=False) == "kubernetes"

    def test_priority_docker_before_ci(self):
        """Docker takes priority over CI."""
        with patch("fapilog.core.environment._detect_docker", return_value=True):
            with patch("fapilog.core.environment.is_ci_environment", return_value=True):
                assert detect_environment(use_cache=False) == "docker"

    def test_detection_caching(self):
        """Detection results are cached."""
        with patch.dict(os.environ, {"AWS_LAMBDA_FUNCTION_NAME": "func"}):
            result1 = detect_environment(use_cache=True)
            # Clear env var
            with patch.dict(os.environ, {}, clear=True):
                result2 = detect_environment(use_cache=True)
                # Should return cached result
                assert result1 == result2 == "lambda"

    def test_cache_bypass(self):
        """Cache can be bypassed."""
        with patch.dict(os.environ, {"AWS_LAMBDA_FUNCTION_NAME": "func"}):
            detect_environment(use_cache=True)  # Cache result
            # Clear env var
            with patch.dict(os.environ, {}, clear=True):
                result = detect_environment(use_cache=False)
                # Should re-detect (not cached)
                assert result != "lambda"
```

### Integration Tests (`tests/integration/test_auto_config.py`)

```python
"""Integration tests for auto-configuration."""

import os
from unittest.mock import patch

import pytest

from fapilog import get_logger


class TestAutoConfiguration:
    """Test auto-configuration per environment."""

    def test_lambda_auto_config(self):
        """Lambda environment gets optimized settings."""
        with patch.dict(os.environ, {"AWS_LAMBDA_FUNCTION_NAME": "my-function"}):
            logger = get_logger(auto_detect=True)
            # Verify settings applied (would need to inspect logger internals)
            # This is a placeholder - actual test would verify batch settings

    def test_kubernetes_auto_enables_enricher(self):
        """Kubernetes environment auto-enables kubernetes enricher."""
        with patch.dict(os.environ, {"POD_NAME": "my-pod"}):
            logger = get_logger(auto_detect=True)
            # Verify kubernetes enricher enabled
            # This is a placeholder - actual test would verify enricher list

    def test_auto_detect_false_uses_defaults_only(self):
        """auto_detect=False uses Story 10.6 defaults only."""
        with patch.dict(os.environ, {"POD_NAME": "my-pod"}):
            logger = get_logger(auto_detect=False)
            # Should not detect Kubernetes, just use defaults

    def test_explicit_environment_override(self):
        """Explicit environment parameter overrides detection."""
        with patch.dict(os.environ, {"POD_NAME": "my-pod"}):
            logger = get_logger(environment="production")
            # Should use production preset, not Kubernetes config
```

### Additional Test Scenarios

- Test: Each environment type detected correctly
- Test: Auto-configuration merges with presets correctly
- Test: Enrichers auto-enabled per environment
- Test: Opt-out mechanism works
- Test: Explicit overrides take precedence
- Test: Detection performance (caching works)
- Test: Edge cases (multiple indicators present)

## Definition of Done

Story is complete when ALL of the following are true:

### Code Complete
- [ ] All acceptance criteria met and verified
- [ ] All tasks completed
- [ ] Code follows project style guide
- [ ] No linting errors or warnings
- [ ] Type checking passes (mypy strict)

### Quality Assurance
- [ ] Unit tests: >90% coverage of new code
- [ ] Integration tests: all scenarios passing
- [ ] Regression tests: no existing functionality broken
- [ ] Performance tests: no regression vs baseline
- [ ] Manual testing completed (if applicable)

### Documentation
- [ ] User-facing docs updated
- [ ] API reference updated (if applicable)
- [ ] Code examples added/updated
- [ ] CHANGELOG.md updated
- [ ] Inline code documentation complete

### Review & Release
- [ ] Code review approved
- [ ] Documentation reviewed for clarity
- [ ] CI/CD pipeline passing
- [ ] Ready for merge to main branch

### Backwards Compatibility
- [ ] No breaking changes OR breaking changes documented with migration guide
- [ ] Existing tests still pass
- [ ] Deprecation warnings added (if applicable)

---

## Risks / Rollback / Monitoring

### Risks

- **Risk:** False positives causing unexpected output changes
  - **Mitigation:** Conservative detection (multiple indicators required where possible)
  - **Mitigation:** Allow opt-out via `auto_detect=False`
  - **Mitigation:** Explicit settings always override
  - **Mitigation:** Clear documentation of detection methods

- **Risk:** Environment detection is slow (filesystem checks)
  - **Mitigation:** Cache detection results per-process
  - **Mitigation:** Optimize checks (check env vars before filesystem)
  - **Mitigation:** Detection only runs when `auto_detect=True`

- **Risk:** Detection misclassifies edge cases (e.g., Docker in Kubernetes)
  - **Mitigation:** Priority order ensures correct classification (K8s > Docker)
  - **Mitigation:** Allow explicit `environment` parameter to override
  - **Mitigation:** Document detection priority and edge cases

- **Risk:** Auto-enabling enrichers causes performance issues
  - **Mitigation:** Enrichers are lightweight (mostly env var reads, cached on start)
  - **Mitigation:** Users can disable enrichers if needed (explicit settings override)
  - **Mitigation:** Kubernetes enricher already exists and is tested
  - **Mitigation:** Enrichers cache metadata on `start()` to avoid repeated reads

### Rollback Plan

- Gate auto-detection behind a flag
- Keep default off if needed
- Explicit settings always override

### Success Metrics / Monitoring

- Log detection decisions in debug mode for visibility (if internal_logging enabled)
- Monitor false positive rate (via user feedback)
- Track environment detection distribution (if telemetry added)
- User feedback on detection accuracy and auto-configuration usefulness

---

## Relationship to Other Stories

### Story 10.6 - Simple Defaults (Dependency)

**Story 10.8 depends on Story 10.6:**
- Uses `is_ci_environment()` helper for CI detection
- Uses `is_tty_environment()` helper for TTY detection
- Uses `get_default_log_level()` helper for log level defaults
- Story 10.6 must be completed before Story 10.8

**Boundary:**
- Story 10.6 = Simple, environment-agnostic defaults (TTY/CI detection)
- Story 10.8 = Advanced, environment-specific auto-configuration (Docker/K8s/Lambda)

### Story 10.2 - Format Detection

**Story 10.8 uses Story 10.2:**
- Output format detection already implemented
- Story 10.8 applies format based on environment (JSON for containers, auto for local)

## Related Documents

- [Story 10.0: Series Overview](./10.0-series-overview.md)
- [Story 10.1: Configuration Presets](./10.1.configuration-presets.md) - ✅ Complete
- [Story 10.2: Pretty Console Output](./10.2.pretty-console-output.md) - ✅ Complete
- [Story 10.6: Enhanced Default Behaviors](./10.6.enhanced-default-behaviors.md) - **Depends on this**
- [Epic 10: Developer Experience](../prd/epic-10-DX-Experience.md)

---

## Change Log

| Date       | Change                                                    | Author |
| ---------- | --------------------------------------------------------- | ------ |
| 2025-01-10 | Migrated to new format                                    | System |
| 2025-01-11 | Clarified Lambda enricher status, improved detection docs | Review |
