# ๐Ÿค– COPILOT AUTO-UPDATE RULE **Copilot MUST update this file automatically when ANY of the following happens:** 1. **User defines or changes** project domain, stack, database, or scale โ†’ Update ๐ŸŽฏ PROJECT IDENTITY 2. **User starts a new task** or completes one โ†’ Update ๐Ÿšง CURRENT FOCUS and โœ… COMPLETED WORK 3. **User makes architectural decisions** โ†’ Update ๐Ÿ“‹ IMPORTANT CONTEXT and ๐Ÿ— PATTERNS TO USE 4. **User adds explicit instructions** (e.g., "always do X", "use Y for Z") โ†’ Add to ๐Ÿ“œ USER INSTRUCTIONS LOG 5. **User provides credentials or config names** โ†’ Add NAME ONLY to ๐Ÿ” CREDENTIALS & CONFIG (โš ๏ธ NEVER store values!) 6. **User says "don't do X"** or prohibits something โ†’ Add to ๐Ÿšซ USER SAID "DON'T DO THIS" 7. **User shares important context** (business rules, constraints, domain knowledge) โ†’ Add to ๐Ÿ“‹ IMPORTANT CONTEXT **After updating, briefly confirm what was changed at the end of the response.** --- ## ๐ŸŽฏ PROJECT IDENTITY | Field | Value | | ------------ | ------------------------------------------------------------------------------------------------------ | | **Name** | LLM Verify | | **Domain** | AI model verification & benchmarking โ€” detect model fraud (e.g., resold APIs misrepresenting identity) | | **Stack** | Python 3.12+ ยท FastAPI ยท Pydantic v2 ยท httpx (async) ยท SQLAlchemy 2.0 (async) ยท Alembic | | **Database** | SQLite (dev & prod โ€” file-based, zero-config) | | **Scale** | Single-node CLI + web dashboard ยท benchmarks run locally or via CI | | **Repo** | `benchmark/` | --- ## ๐Ÿ“œ USER INSTRUCTIONS LOG | # | Date | Instruction | | --- | ---------- | ------------------------------------------------ | | 1 | 2026-02-17 | Project bootstrapped with Copilot context system | | | | | --- ## โœ… COMPLETED WORK | # | Date | Task | | --- | ---------- | ----------------------------------------------------------------------- | | 1 | 2026-02-17 | Project bootstrap โ€” copilot context, settings, gitignore | | 2 | 2026-02-17 | Full project scaffolding โ€” 30+ files, all layers, 32 prompts | | 3 | 2026-02-17 | All 9 unit tests passing | | 4 | 2026-02-17 | Renamed to LLM Verify, pushed to GitHub | | 5 | 2026-02-17 | Fixed factory: suspect provider now uses Anthropic protocol by default | | 6 | 2026-02-17 | First live benchmark โ€” identity probes vs suspect API (opuscode.pro) | | 7 | 2026-02-17 | Confirmed fraud: suspect serves Claude 3.5 Sonnet as Claude Sonnet 4 | | 8 | 2026-02-17 | Updated README with no-API-key usage guide and red flags doc | | 9 | 2026-02-17 | Added deep analysis feature โ€” service, schemas, handler, README section | --- ## ๐Ÿšง CURRENT FOCUS | Item | Detail | | -------------- | ------------------------------------------------------------------- | | **Working on** | Deep analysis feature complete โ€” ready for live testing | | **Blockers** | None | | **Next up** | Live test deep analysis endpoint, web dashboard, more prompt suites | --- ## ๐Ÿ” CREDENTIALS & CONFIG > โš ๏ธ **NEVER store actual values here โ€” names/keys only!** | # | Name | Service | Notes | | --- | -------------------- | ------------ | ------------------------------------ | | 1 | SUSPECT_API_KEY | opuscode.pro | Suspect API key โ€” Anthropic protocol | | 2 | SUSPECT_API_BASE_URL | opuscode.pro | https://opuscode.pro/api | --- ## ๐Ÿšซ USER SAID "DON'T DO THIS" | # | Date | Prohibition | | --- | ---- | ----------- | | | | | --- ## ๐Ÿ“‹ IMPORTANT CONTEXT - **Core Problem:** Users are being sold API access to models misrepresented as premium models (e.g., Kimi sold as Claude). The system prompt says "Claude" but the underlying model is actually Kimi. - **Goal:** Build a benchmark suite that can fingerprint AI model behavior to verify true model identity, comparing response patterns, capabilities, and quirks across models. - **Suspect API (opuscode.pro):** Uses **Anthropic Messages protocol**, NOT OpenAI. Endpoint: `https://opuscode.pro/api/v1/messages`. Auth header: `x-api-key`. Available models: `Opus 4.6`, `Sonnet 4.5`, `Haiku 4.5` (their naming). Default model: `Opus 4.6`. - **First test result:** Suspect claims to be Claude Sonnet 4 but self-identifies as **claude-3-5-sonnet-20241022** (Claude 3.5 Sonnet). Gave 3 different knowledge cutoffs, mentions "custom proxy server", avg latency 14s. - **Factory mapping:** `suspect` provider defaults to `anthropic` protocol. Can be overridden via `protocol` field in ModelConfig. - **Key Features Planned:** - Run standardized prompt suites against multiple API endpoints - Collect and store structured benchmark results (latency, token usage, response quality) - Statistical comparison & fingerprinting to detect model identity - Web dashboard to visualize results - CLI for running benchmarks in CI/CD --- ## ๐Ÿšจ HARD RULES ### Security - โŒ **NEVER** commit secrets, API keys, or tokens to code or config files - โœ… Use `.env` files (gitignored) and `pydantic-settings` for all secrets - โœ… Parameterized queries only โ€” no string interpolation in SQL - โœ… Validate all external input with Pydantic models ### Performance - โœ… Use `async/await` for all I/O (HTTP calls, DB queries, file ops) - โœ… Use `httpx.AsyncClient` with connection pooling for API calls - โœ… Use SQLAlchemy async sessions with proper context managers - โœ… Batch concurrent API calls with `asyncio.gather()` where appropriate ### Architecture - โœ… Dependency injection via FastAPI `Depends()` - โœ… Strict separation: handlers โ†’ services โ†’ repositories โ†’ models - โœ… Each layer has a single responsibility - โœ… Config is centralized in one place (`src/config.py`) --- ## ๐Ÿ“ CODE STYLE - **Type hints** on ALL function signatures and return types - **Docstrings** on all public functions (Google style) - **Descriptive names** โ€” no single-letter variables except `i`, `_` in comprehensions - **Early returns** to reduce nesting - **Max 30 lines** per function โ€” extract helpers if longer - **Pydantic models** for all data structures crossing boundaries - **f-strings** for string formatting - **`pathlib.Path`** over `os.path` --- ## ๐Ÿ— PATTERNS TO USE | Pattern | Usage | | ---------------------- | ---------------------------------------------------------------- | | **Result pattern** | Return `Result[T, Error]` for operations that can fail | | **Service pattern** | Business logic lives in service classes, not in handlers | | **Repository pattern** | DB access abstracted behind repository interfaces | | **Adapter pattern** | Each AI provider gets an adapter implementing a common interface | | **Factory pattern** | Create model adapters dynamically from config | | **Strategy pattern** | Benchmark suites are pluggable strategies | --- ## ๐Ÿšซ PATTERNS TO AVOID | Anti-pattern | Why | | ------------------------- | --------------------------------------------------- | | **God objects** | Split into focused, single-responsibility classes | | **Magic numbers/strings** | Use enums and constants | | **Mutable global state** | Use DI and explicit passing | | **Generic `utils.py`** | Create specific modules (`string_helpers.py`, etc.) | | **Bare `except:`** | Always catch specific exceptions | | **Print debugging** | Use `structlog` or `logging` | | **Nested callbacks** | Use async/await | --- ## ๐Ÿ“ PROJECT STRUCTURE ``` benchmark/ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ main.py # FastAPI app entry point โ”‚ โ”œโ”€โ”€ config.py # Pydantic Settings configuration โ”‚ โ”œโ”€โ”€ database.py # SQLAlchemy engine & session setup โ”‚ โ”œโ”€โ”€ handlers/ # API route handlers (thin layer) โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ benchmarks.py โ”‚ โ”‚ โ””โ”€โ”€ results.py โ”‚ โ”œโ”€โ”€ services/ # Business logic โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ benchmark_runner.py โ”‚ โ”‚ โ”œโ”€โ”€ model_comparator.py โ”‚ โ”‚ โ””โ”€โ”€ fingerprint.py โ”‚ โ”œโ”€โ”€ repositories/ # Database access โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ benchmark_repo.py โ”‚ โ”‚ โ””โ”€โ”€ result_repo.py โ”‚ โ”œโ”€โ”€ models/ # SQLAlchemy ORM models โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ benchmark.py โ”‚ โ”‚ โ””โ”€โ”€ result.py โ”‚ โ”œโ”€โ”€ schemas/ # Pydantic request/response schemas โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ benchmark.py โ”‚ โ”‚ โ””โ”€โ”€ result.py โ”‚ โ”œโ”€โ”€ adapters/ # AI provider adapters โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”‚ โ”œโ”€โ”€ base.py # Abstract base adapter โ”‚ โ”‚ โ”œโ”€โ”€ openai_adapter.py โ”‚ โ”‚ โ”œโ”€โ”€ anthropic_adapter.py โ”‚ โ”‚ โ””โ”€โ”€ generic_adapter.py # For OpenAI-compatible APIs โ”‚ โ””โ”€โ”€ prompts/ # Benchmark prompt suites โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ identity.py # "Who are you?" probes โ”‚ โ”œโ”€โ”€ capability.py # Capability-specific tests โ”‚ โ””โ”€โ”€ fingerprint.py # Behavioral fingerprinting prompts โ”œโ”€โ”€ tests/ โ”‚ โ”œโ”€โ”€ __init__.py โ”‚ โ”œโ”€โ”€ conftest.py # Shared fixtures โ”‚ โ”œโ”€โ”€ test_benchmark_runner.py โ”‚ โ”œโ”€โ”€ test_model_comparator.py โ”‚ โ””โ”€โ”€ test_adapters/ โ”‚ โ””โ”€โ”€ test_generic_adapter.py โ”œโ”€โ”€ alembic/ # Database migrations โ”‚ โ””โ”€โ”€ versions/ โ”œโ”€โ”€ alembic.ini โ”œโ”€โ”€ .env.example โ”œโ”€โ”€ .gitignore โ”œโ”€โ”€ pyproject.toml โ””โ”€โ”€ README.md ``` --- ## ๐Ÿ”‘ ENVIRONMENT VARIABLES ```env # === REQUIRED === DATABASE_URL=sqlite+aiosqlite:///./benchmarker.db # === AI PROVIDER API KEYS (add as needed) === # OPENAI_API_KEY= # ANTHROPIC_API_KEY= # SUSPECT_API_KEY= # The API you're testing/verifying # SUSPECT_API_BASE_URL= # Base URL of the suspect API # === OPTIONAL === # LOG_LEVEL=INFO # BENCHMARK_TIMEOUT=30 # Seconds per API call # MAX_CONCURRENT_CALLS=5 # Limit parallel API requests ``` --- ## ๐Ÿ“š GLOSSARY | Abbreviation | Meaning | | ---------------- | ------------------------------ | | `ctx` | Context | | `repo` | Repository | | `svc` | Service | | `dto` | Data Transfer Object | | `handler` | API route handler (controller) | | `adapter` | AI provider adapter | | `cfg` / `config` | Configuration | | `db` | Database | | `req` / `res` | Request / Response | | `bench` | Benchmark | | `fp` | Fingerprint | --- ## โœ… TESTING - **Test alongside code** โ€” tests mirror `src/` structure - **Mock all externals** โ€” API calls, database, file system - **Cover edge cases** โ€” empty inputs, timeouts, malformed responses - **Target 80% coverage** minimum - **Use `pytest`** with `pytest-asyncio` for async tests - **Fixtures in `conftest.py`** โ€” shared test data and mocks - **Test naming:** `test___` (e.g., `test_run_benchmark_timeout_raises_error`) - **Use `httpx.AsyncClient`** for integration testing FastAPI endpoints