Scout

wiki/sources/legacy/Design-2026-05-03-phase1-complete.md

Scout Design Log — Phase 1 Complete (2026-05-03)

What Was Built This Session (continuation from earlier in day)

Phase 1 is now fully built across all components:

Component Files Commit
FastAPI service scout/api/config.py, deps.py, main.py, middleware/auth.py, routers/ (6 files) c040bb9
Docker docker/Dockerfile, docker/docker-compose.yml, .env.example d96481c
Claude skill scout/skill/scout.md 29344d1

FastAPI Architecture Decisions

get_crawler lives in deps.py, not main.py

Circular import issue: routers need to import get_crawler, and main.py imports routers. Putting get_crawler in deps.py breaks the cycle cleanly. main.py re-exports it via from scout.api.deps import get_crawler so test imports still work.

ScoutCrawler as lifespan singleton

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.crawler = ScoutCrawler(llm_api_key=settings.llm_api_key)
    yield

Never constructed per-request. Required for testability — tests override via app.dependency_overrides[get_crawler] = lambda: mock_crawler.

Auth middleware exempts /health

AuthMiddleware(BaseHTTPMiddleware) reads X-API-Key header. /health path bypasses auth entirely — required for Docker healthcheck to work without credentials.

Routers have zero error handling

All error handling is in the mode functions (catch + return success=False). Routers are pure delegation — one line each. 4xx errors come only from auth (403) and Pydantic validation (422).

Docker Architecture Decisions

shm_size: 1gb is mandatory

Playwright's Chromium uses /dev/shm for inter-process communication. Default Docker shared memory (64MB) causes browser crashes under load. shm_size: '1gb' in docker-compose.yml prevents this.

System deps installed explicitly (not via playwright install-deps)

playwright install-deps chromium requires root and works on Debian/Ubuntu but is fragile across Docker base images. Explicit apt-get install of known Chromium deps is more reliable and audit-friendly.

Build context is .. (repo root), not docker/

Dockerfile COPYs pyproject.toml and scout/ from the repo root. docker-compose.yml sets context: .. to make this work.

Scope Decision: No fact-checking in Scout

Arijit proposed adding Perplexity cross-validation to Scout (crawl + search = fact-check). Rejected: - Violates single responsibility — Scout is a crawler, not a validator - This already exists in PRISM's intel_company 3-track pipeline (WebFetch + Perplexity + Synthesis LLM) - Adds latency and Perplexity API key dependency to every Scout consumer - Reconciliation logic belongs in the application layer (PRISM), not infrastructure (Scout)

Test State at Phase 1 Complete

Unit + contract:  70 passing
Integration:       6 passing (real Crawl4AI v0.7.7)
pyright:           0 errors
ruff:              clean

Unit tests for API use app.dependency_overrides — no real Crawl4AI, no network.

What's Not Done Yet

  1. Smoke test — HTTP stack (uvicorn scout.api.main:app + real curl) never run
  2. PRISM Phase 4 — intel_hiring + intel_company migration to ScoutCrawler not started
  3. Skill registrationscout/skill/scout.md written but not installed in Claude Code
  4. Extract integration test — skipped (needs LLM API key); manual verification needed

Next Session Entry Point

Run smoke test first (SESSION.md has exact commands). Then PRISM Phase 4.