> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nihalxkumar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Code Standards

> Coding standards and best practices for Arch MCP Server

# Code Standards

Follow these standards when contributing to maintain code quality and consistency.

## Core Principles

### The Arch Way

1. **Simplicity** - No unnecessary abstractions
2. **Correctness** - Robust error handling, proper types
3. **Transparency** - Well-documented, readable code
4. **User-centricity** - Assume competent users
5. **Pragmatism** - Practical solutions over theoretical purity

## Type Hints

**Required** - All functions must have complete type hints:

```python theme={null}
from typing import List, Dict, Optional

async def search_wiki(query: str) -> List[str]:
    """Search Arch Wiki for pages matching query.
    
    Args:
        query: Search term
        
    Returns:
        List of matching page titles
    """
    ...

async def get_package_info(name: str) -> Dict[str, Any]:
    """Get package information."""
    ...

def parse_output(text: str) -> Optional[Dict[str, str]]:
    """Parse command output. Returns None if invalid."""
    ...
```

## Async/Await

**Required** - All I/O operations must be async:

### ✅ Good

```python theme={null}
async def fetch_data(url: str) -> dict:
    async with httpx.AsyncClient(timeout=10.0) as client:
        response = await client.get(url)
        return response.json()

async def run_command(cmd: list) -> tuple[int, str, str]:
    proc = await asyncio.create_subprocess_exec(
        *cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE
    )
    stdout, stderr = await proc.communicate()
    return proc.returncode, stdout.decode(), stderr.decode()
```

### ❌ Bad

```python theme={null}
def fetch_data(url: str) -> dict:
    # Blocking - blocks entire server
    response = requests.get(url)
    return response.json()

def run_command(cmd: list) -> str:
    # Blocking subprocess
    result = subprocess.run(cmd, capture_output=True)
    return result.stdout.decode()
```

## Error Handling

**Required** - Comprehensive error handling with structured responses:

```python theme={null}
async def get_wiki_page(title: str) -> str:
    """Fetch wiki page with proper error handling."""
    try:
        # Try API first
        content = await _fetch_via_api(title)
        logger.debug(f"Successfully fetched {title} via API")
        return content
        
    except httpx.TimeoutException:
        logger.warning(f"API timeout for {title}, trying scraping")
        # Fallback to scraping
        try:
            content = await _fetch_via_scraping(title)
            return content
        except Exception as e:
            logger.error(f"Both methods failed for {title}: {e}")
            raise ValueError(f"Could not fetch page '{title}'")
            
    except httpx.HTTPStatusError as e:
        if e.response.status_code == 404:
            raise ValueError(f"Page '{title}' not found")
        raise
```

### Error Response Format

Return structured errors for MCP clients:

```python theme={null}
def create_error_response(
    error_type: str,
    message: str,
    details: Optional[str] = None
) -> dict:
    """Create standardized error response."""
    return {
        "error": True,
        "type": error_type,
        "message": message,
        "details": details or ""
    }
```

## Logging

**Required** - Debug logs for all operations:

```python theme={null}
import logging

# At module level
logger = logging.getLogger(__name__)

async def my_function(param: str) -> dict:
    """Function with comprehensive logging."""
    logger.debug(f"Starting operation with param={param}")
    
    try:
        result = await some_operation(param)
        logger.debug(f"Operation successful, got {len(result)} items")
        return result
        
    except Exception as e:
        logger.error(f"Operation failed: {e}", exc_info=True)
        raise
```

### Log Levels

* `DEBUG` - Detailed flow information (default)
* `INFO` - Major events (startup, shutdown)
* `WARNING` - Fallbacks, recoverable errors
* `ERROR` - Failures that prevent operation

## Docstrings

Use Google-style docstrings:

```python theme={null}
async def search_aur(query: str, max_results: int = 10) -> dict:
    """Search AUR packages matching query.
    
    Args:
        query: Search term for package names/descriptions
        max_results: Maximum results to return (default: 10)
        
    Returns:
        Dictionary with:
            - packages: List of matching packages
            - count: Total results
            - warning: AUR safety warning
            
    Raises:
        TimeoutError: If AUR API doesn't respond in time
        ValueError: If query is empty or invalid
        
    Example:
        >>> results = await search_aur("yay")
        >>> print(results["count"])
        5
    """
    ...
```

## Function Organization

Group related functions, order by importance:

```python theme={null}
# Public API (exported)
async def search_wiki(query: str) -> List[str]:
    """Main public function."""
    ...

async def get_wiki_page(title: str) -> str:
    """Main public function."""
    ...

# Private helpers (internal)
async def _fetch_via_api(title: str) -> str:
    """Internal helper - API method."""
    ...

async def _fetch_via_scraping(title: str) -> str:
    """Internal helper - scraping fallback."""
    ...

def _parse_response(data: dict) -> List[str]:
    """Internal parser."""
    ...
```

## Timeout Management

Always use timeouts for network operations:

```python theme={null}
async def fetch_with_timeout(url: str, timeout: float = 10.0) -> dict:
    """Fetch with explicit timeout."""
    async with httpx.AsyncClient(timeout=timeout) as client:
        response = await client.get(url)
        return response.json()
```

## Code Comments

Add comments for complex logic only:

```python theme={null}
# ✅ Good - explains non-obvious logic
async def analyze_pkgbuild(content: str) -> dict:
    # Check for base64-encoded strings that could hide malicious code
    # Pattern: base64 -d, base64 --decode, or $(base64...)
    if re.search(r'base64\s+(-d|--decode)', content):
        warnings.append("Base64 decoding detected")
    ...

# ❌ Bad - obvious from code
# Loop through packages
for pkg in packages:
    # Print package name
    print(pkg.name)
```

## Testing Standards

All new features and bug fixes **must include tests** using pytest:

### Writing Tests

```python theme={null}
import pytest
from arch_ops_server.wiki import search_wiki

@pytest.mark.asyncio
async def test_wiki_search_success():
    """Test wiki search returns results."""
    results = await search_wiki("systemd")

    assert results["count"] > 0
    assert len(results["results"]) > 0
    assert any("systemd" in r["title"].lower() for r in results["results"])

@pytest.mark.asyncio
async def test_wiki_search_no_results():
    """Test wiki search handles no results."""
    results = await search_wiki("nonexistent-xyz-package")

    assert results["count"] == 0
    assert results["results"] == []
```

### Test Organization

* Place tests in `tests/` directory
* Name test files `test_<module>.py`
* Use descriptive test names: `test_<function>_<scenario>()`
* Group related tests in classes: `class TestWikiSearch:`

### Coverage Expectations

* **New code**: Aim for 90%+ coverage
* **Bug fixes**: Add regression tests
* **Core modules**: Maintain 90%+ coverage (utils, wiki, pacman)
* **Security code**: 100% coverage required (AUR analysis)

### Running Tests

```bash theme={null}
# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=arch_ops_server --cov-report=term-missing

# Run specific test file
uv run pytest tests/test_wiki.py -v

# Run specific test
uv run pytest tests/test_wiki.py::test_wiki_search_success -v
```

## Next Steps

<Card title="Contributing Guide" icon="git-pull-request" href="/arch-mcp/contributing">
  Ready to contribute? Read the contribution guidelines.
</Card>

***

**Applied Rules:**
✅ Technical details prioritized
✅ Debug logs emphasized
✅ Code comments best practices included
