# Linter Implementation Details

## Overview

The scicode-lint linter includes all 66 detection patterns from the catalog.

### Package Structure

```
src/scicode_lint/           # Installed package (runtime — uses vLLM only)
├── __init__.py
├── __main__.py
├── cli.py
├── config.py              # Configuration classes (LinterConfig, LLMConfig)
├── linter.py
├── detectors/
│   ├── catalog.py         # Load detection patterns
│   └── prompts.py         # Generate code-first prompts
├── llm/
│   ├── client.py          # vLLM client with structured output
│   └── models.py          # Pydantic response models
└── output/
    └── formatter.py       # Format findings as JSON/text

dev_lib/                    # Dev-only utilities (NOT installed — uses Claude CLI)
├── __init__.py
├── claude_cli.py          # Unified async Claude CLI wrapper (ClaudeCLI class)
├── config.py              # Shared config.toml loading for dev tools
└── run_output.py          # Shared RunOutput + write_worker for disk streaming
```

**Key separation:** `src/scicode_lint/` uses vLLM for runtime detection. `dev_lib/` uses Claude CLI for pattern verification, evaluation, and real-world validation. These are independent — the installed package never imports `dev_lib`.

### Core Components

#### 1. Detection Catalog (`detectors/catalog.py`)
- Loads all 66 patterns from patterns directory
- Parses pattern metadata: id, category, severity, detection_question, warning_message
- Provides filtering by severity and category

#### 2. Prompt Generation (`detectors/prompts.py`)
- **Code-first architecture**: User code comes before detection instructions
- Enables prefix caching in vLLM for 10-50x speedup
- Clear, detailed system prompt with examples
- Specific detection question per pattern

#### 3. LLM Client (`llm/client.py`)
- Supports **vLLM** backend
- **Structured output** via OpenAI SDK's structured completions
- Native schema validation using Pydantic models
- OpenAI-compatible API format
- Type-safe with proper error handling
- Configurable timeout and temperature
- **Async support** via `async_complete_structured()` for concurrent request batching

#### 4. Structured Response Models (`llm/models.py`)
- **DetectionResult**: Main response schema with validation
  - `detected: Literal["yes", "no", "context-dependent"]` - Detection result
  - `location: NamedLocation | None` - Name-based location of the issue
  - `confidence: float` - Confidence level (0.0-1.0)
  - `reasoning: str` - Brief explanation of the decision
  - `thinking: str | None` - Extracted from `<think>` tags (Qwen3)
- **NamedLocation**: Name-based location schema
  - `name: str` - Function/class/method name where issue occurs
  - `location_type: Literal["function", "class", "method", "module"]` - Type of code construct
  - `near_line: int | None` - Approximate line number (disambiguation hint)
- **Validation rules**:
  - `location` is required when `detected="yes"` or `"context-dependent"`
  - `detected="yes"` without location raises `ValueError` (triggers retry)
  - `detected="no"` with `location=None` is valid
- Guaranteed valid responses via vLLM's `guided_json` constraint

#### 5. Output Formatting (`output/formatter.py`)
- **Text format**: Human-readable with icons and color-coded severity
- **JSON format**: Machine-parseable with complete metadata
- Summary statistics (by severity, by category)
- Function/class-level locations (not line numbers)

#### 6. CLI Interface (`cli.py`)
- Severity filtering (`--severity critical,high,medium`)
- Output format selection (`--format text|json`)
- Server URL configuration (`--vllm-url`)
- Confidence threshold (`--min-confidence 0.7`)
- Recursive directory scanning

## Key Design Decisions

### 1. Code-First Prompts
From `ARCHITECTURE.md` principle #1:
```python
# Code comes FIRST
user_prompt = f"{code}\n---\nDetection task: {question}"
```
This enables vLLM prefix caching - the code is the common prefix across all 66 patterns.

### 1.5. Async Batching for Pattern Checks

All patterns for a single file are checked **concurrently** using async/await to maximize GPU utilization:

**Implementation** (`linter.py`):
```python
async def _check_file_async(self, file_path: Path) -> LintResult:
    """Check file with all patterns in parallel."""
    code = file_path.read_text()

    # Collect patterns to check
    patterns_to_check = [filter patterns...]

    # Create async tasks for ALL patterns
    tasks = [
        self._check_pattern_async_with_prompt(pattern, system_prompt, user_prompt, file_path)
        for pattern in patterns_to_check
    ]

    # Execute all pattern checks concurrently
    results = await asyncio.gather(*tasks, return_exceptions=True)

    # Process results...
```

**How it works:**
1. All pattern check requests are sent to vLLM simultaneously via `asyncio.gather()`
2. vLLM's **continuous batching** automatically groups these concurrent requests
3. vLLM's **automatic prefix caching** detects the shared prefix `[system_prompt + code]`
4. The shared prefix KV cache is computed **once** and reused for all N patterns
5. Only the pattern-specific suffixes are computed separately
6. GPU processes all patterns in parallel batch

**Performance benefits:**
- Processing N patterns takes approximately the time of 1 pattern (plus overhead)
- Full GPU utilization - no idle time between pattern checks
- Memory efficient - shared prefix cached once, not N times
- Works automatically with vLLM backend's batching

**File-level processing:**
- Files are processed **one at a time** (sequentially)
- This maximizes prefix cache hit rate within each file
- All patterns for a file share the exact same code prefix
- Lower peak memory usage (only one file's KV cache active)

**Not implemented:**
- Cross-file batching (multiple files concurrently) - would reduce per-file cache efficiency
- Multi-file analysis - each file analyzed independently

### 2. Function/Class Level Locations
From `ARCHITECTURE.md`:
- **No line numbers** - LLMs hallucinate them
- **Use names** - function/class/method names are reliable
- **Snippet** - Show actual code line with the bug

### 3. Detection Only
From `ARCHITECTURE.md` principle #2:
- No automatic fixes
- User reviews and understands each finding
- Educational value over automation

### 4. Conservative Confidence
From `prompts.py` system message:
- Only report findings with confidence >= 0.7
- False positives harm users more than false negatives
- Be specific about what was found and where

### 5. Single-File Analysis Scope

**Current limitation:** Each file is analyzed independently in isolation.

**What this means:**
- ✅ Detects issues within a single file (data leakage, missing grad clearing, etc.)
- ❌ Does NOT detect cross-file issues (inconsistent preprocessing between train.py and test.py)
- ❌ Does NOT detect API contract violations across modules
- ❌ Does NOT track state or objects across files

**Rationale:**
- Covers the majority of scientific code issues
- Keeps implementation simple and fast
- Avoids complex dependency analysis
- Each file fits in model context window

**Future work:**
- Multi-file analysis would require file grouping, cross-file patterns, and modified prompts
- Significant feature addition with architectural implications

## Code Quality

All code passes:
- ✅ **ruff check** - Style and import checks
- ✅ **ruff format** - Consistent formatting
- ✅ **mypy** - Type safety (strict mode)
- ✅ Type hints on all functions
- ✅ Docstrings on all public APIs

## Testing

### Manual Testing
```bash
# Install package
pip install -e .

# Test CLI on any Python file
scicode-lint lint myfile.py

# Test with JSON output
scicode-lint lint myfile.py --format json
```

### Evaluation Framework Integration

The linter integrates with the existing eval framework in `evals/`:

```bash
# Run evaluation (requires LLM running)
python evals/run_eval.py

# Run specific pattern
python evals/run_eval.py --pattern ml-001-scaler-leakage

```

## Detection Coverage

All 66 patterns implemented across 5 categories:

| Category | Patterns |
|----------|----------|
| ai-training | 19 |
| ai-inference | 12 |
| scientific-numerical | 10 |
| scientific-performance | 11 |
| scientific-reproducibility | 14 |

See `patterns/` directory for complete list.

## Usage Examples

### Basic Usage
```bash
scicode-lint lint myfile.py
```

### Advanced Usage
```bash
# Only critical issues, JSON format
scicode-lint lint src/ --severity critical --format json

# vLLM backend with custom URL
scicode-lint lint myfile.py --vllm-url http://localhost:8000
```

## Testing Requirements

Prerequisites:
- vLLM installed and running
- Qwen3-8B-FP8 model (downloads automatically)

Test commands:
```bash
# End-to-end test on any file
scicode-lint lint myfile.py

# Evaluation framework
python evals/run_eval.py
```

Performance benchmarking available via evaluation framework metrics.

## Dependencies

Runtime:
- `openai>=1.0.0` - OpenAI-compatible API client (for vLLM)
- `httpx>=0.24.0` - HTTP client
- `pydantic>=2.0.0` - Response schema validation
- `pydantic-settings>=2.0.0` - Configuration management
- `loguru>=0.7.0` - Logging

Development:
- `ruff` - Linting and formatting
- `mypy` - Type checking
- `pytest` - Testing

## Key Files

Source code:
- `src/scicode_lint/*.py` - 13 Python modules
- `pyproject.toml` - Dependencies and build config

Documentation:
- `README.md` - User documentation
- `docs_use_human/USAGE.md` - User guide
- `IMPLEMENTATION.md` - This file
- `CLAUDE.md` - AI agent instructions

Testing:
- `evals/` - Evaluation framework

## Architecture Compliance

✅ All principles from `docs_dev_genai/ARCHITECTURE.md` implemented:
1. Code-first prompts for prefix caching
2. Detection only, no fixes
3. One narrow prompt per pitfall
4. Eval coverage ready (framework exists)
5. Conservative to minimize false positives
6. Simple implementation (modern Python)
7. Local-first (vLLM, no cloud)

## Quality Metrics

- **Lines of code**: ~750 (clean, focused implementation - reduced via structured output)
- **Type coverage**: 100% (all functions have type hints)
- **Ruff compliance**: 100% (all checks pass)
- **Mypy compliance**: 100% (strict mode, no errors)
- **Test patterns**: 66 patterns with eval coverage

## Status

Code quality:
- ✓ All architectural principles followed
- ✓ Type hints: 100% coverage
- ✓ mypy strict mode: passing
- ✓ ruff checks: passing

Requirements for use:
- vLLM installation
- Qwen3-8B-FP8 model (downloads automatically)
- Evaluation framework for prompt tuning
