ruben de la fuente
feat: update with Claude-extracted benchmarks and UI fixes
39a2a9f
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
npm run dev # start dev server at localhost:3000
npm run build # production build (uses standalone output for Docker)
npm run lint # eslint
npx tsc --noEmit # type-check without building
npm run extract # run PDF β†’ benchmarks.json extraction (requires Ollama or HF)
```
## Environment
Copy `.env.local.example` to `.env.local` before running locally. Ollama must be running (`ollama serve`) with `llama3.1:8b` pulled.
The LLM provider is swapped entirely via env vars β€” no code changes needed:
- **Local (Ollama):** `OLLAMA_BASE_URL=http://localhost:11434/v1`, `LLM_MODEL=llama3.1:8b`
- **HF Spaces:** `OLLAMA_BASE_URL=https://router.huggingface.co/v1`, `LLM_MODEL=Qwen/Qwen2.5-72B-Instruct`, `OPENAI_API_KEY=hf_...`
- **OpenAI:** set `OPENAI_API_KEY`, `LLM_MODEL=gpt-4o`, remove `OLLAMA_BASE_URL`
## Architecture
The app has two distinct flows:
**One-time setup:** `scripts/extract-knowledge.ts` reads PDFs from `data/pdfs/`, chunks text into ~8000-char pieces, sends each to the LLM, merges results into `data/benchmarks.json` (47 patterns, 124 insights from 3 DORA reports). This file is committed and bundled into the Docker image β€” the script does not run at runtime.
**Request flow:** Browser form (`app/page.tsx`, two steps) β†’ POST `/api/interpret` β†’ `lib/benchmarks.ts` loads `benchmarks.json` (cached in memory) β†’ `lib/prompts.ts` builds system prompt with benchmark data β†’ `lib/llm.ts` calls LLM via OpenAI-compatible client β†’ response validated with `InterpretationReportSchema` (Zod) β†’ JSON returned β†’ stored in `sessionStorage` β†’ `app/report/page.tsx` reads and renders report.
**LLM abstraction:** All LLM calls go through `lib/llm.ts`, which wraps the `openai` npm package. The provider is controlled entirely by `OLLAMA_BASE_URL`, `OPENAI_API_KEY`, and `LLM_MODEL` env vars. The OpenAI client's `baseURL` is set to `OLLAMA_BASE_URL`, making any OpenAI-compatible endpoint (Ollama, HF router, Groq, OpenAI) work without code changes.
## Key constraints
- `lib/schema.ts` defines both input schemas (`MetricsInputSchema`, `TeamContextSchema`) and output schema (`InterpretationReportSchema`). The API route validates both directions β€” 400 for bad input, 422 if the LLM returns a malformed report.
- `lib/benchmarks.ts` sanitizes `data/benchmarks.json` before Zod validation (Ollama sometimes returns arrays instead of strings in pattern fields).
- `next.config.ts` sets `output: 'standalone'` (required for Docker) and `serverExternalPackages: ['pdf-parse']`.
- `tsconfig.json` has a `"ts-node"` override block with `module: "CommonJS"` so scripts in `scripts/` can use `require`-style resolution while the Next.js app uses bundler resolution.
- The `sessionStorage` key is defined in `lib/constants.ts` as `REPORT_SESSION_KEY` β€” use that constant, not the string literal.
- Print/PDF export uses `window.print()` with `@media print` CSS in `globals.css`. Elements to hide during print get the `print-hide` class.
## Deployment
The app is deployed on HuggingFace Spaces at `rdlf/devops-metrics-interpreter`. To update, push to the `hf-deploy` branch (orphan, no PDF history) and force-push to `hf:main`. Do not push `data/pdfs/` β€” those files exceed HF's 10MB limit and are gitignored.