# TechTitans — Repair device recognition: live-AI verification

**Scope:** verify the real OpenAI vision integration behind Photo-First repair intake. **Branch:**
`techtitans/repair-r1`. **No code was modified** (no defect found) — this is a verification record only.

## 1. Configuration status (checked without exposing the key)

- `.env` contains **no** `AI_REPAIR_*` / `OPENAI_*` keys (checked by name only; no value printed).
- `config/ai_repair.php` → `vision.driver` defaults to **`none`**, `vision.api_key` unset, model
  `gpt-4o-mini`, base `https://api.openai.com/v1`.
- **Live** `GET /api/v1/repairs/intake/capabilities` → `vision.configured = false`, `driver = none`
  (draft = mock/on, transcription = off).

**Conclusion: real vision is NOT configured. The live recognition test is BLOCKED.** No mock output is
presented as real recognition.

## 2. Integration path — inspected and verified sound

`app/AI/Repair/Openai/OpenAiRepairImageAnalyzer.php` is correct and production-ready:

- **Fails closed:** empty `api_key` → `AiRepairNotConfiguredException` (503). Any HTTP failure / rate-limit /
  timeout / non-JSON body → `AiRepairGenerationFailedException` (502).
- **Request:** `POST {base}/chat/completions` with `Http::withToken($key)`, `model` = config
  (`gpt-4o-mini`, vision-capable), `response_format: json_object`, `temperature: 0`, and the image sent
  inline as a base64 `image_url` data URL.
- **Prompt:** STRICT-JSON, extract **only VISIBLE** attributes (`device_category, brand, model,
  visible_damage, condition, uncertain[], missing[]`); **model set null + listed in `missing` unless
  clearly printed**; **NEVER** invent imei / serial / diagnosis / price / technician / warranty.
- **Output** is coerced to the contract (`RepairDraftShape::coerceVision`) before leaving the class.

The frontend consumes this at `POST /repairs/intake/analyze-image`, populates the confirmation screen,
flags uncertain fields "Needs confirmation", preserves staff corrections, and never auto-creates
brands/categories.

## 3. Tests run (this verification)

- **Live:** `capabilities` → `vision.configured=false`; `analyze-image` → **503
  `ai_repair_vision_not_configured`** with `required_env = [AI_REPAIR_VISION_DRIVER=openai,
  AI_REPAIR_VISION_API_KEY]`. Fail-closed confirmed.
- **Backend** `php artisan test --filter=RepairIntakeAiTest` → **11 passed (65 assertions)**, incl.
  "vision not configured by default returns 503", "vision with mock driver returns visible attributes
  only", "capabilities reports honest flags", **"capabilities reports openai configured when key
  present"** (the real driver is correctly detected once a key exists), and "intake ai requires manage
  permission".
- **Frontend** photo-first flow (`NewRepairPhotoFirst.test.tsx` + repair suite) → **62 passing** — Identify
  → Confirm (uncertain chip) → edit-preserved → Fault → Customer → Review → Create, photo persists, single
  ticket on double-click, not-configured fallback. (Exercised with the test-only mock vision driver.)

## 4. Actual AI recognition quality

**Unverified — cannot be assessed without a configured provider.** No real OpenAI vision call was made
(no key), so category/brand/model/condition accuracy on a real device photo is unknown. The integration
is wired correctly and will exercise the real model the moment a key is set.

## 5. Exact configuration to enable + verify real recognition

Add to `backend/.env` (server-side only — never commit the key):

```
AI_REPAIR_VISION_DRIVER=openai
AI_REPAIR_VISION_API_KEY=sk-...          # key with access to a vision-capable model
# optional overrides:
AI_REPAIR_VISION_MODEL=gpt-4o-mini       # must be vision-capable (gpt-4o / gpt-4o-mini)
AI_REPAIR_VISION_BASE_URL=https://api.openai.com/v1
AI_REPAIR_VISION_TIMEOUT=60
```

Then: `php artisan config:clear` and restart the API (`php artisan serve --host=127.0.0.1 --port=8010`).
`capabilities.vision.configured` will flip to `true` and "Identify Device" will run the live model. Once
set, provide a non-sensitive sample device photo and I will run and report real recognition quality.

## 6. Limitations / notes

- Real recognition quality unverified (no key) — the single remaining blocker.
- Colour is not part of the R1 vision contract (manual field).
- `gpt-image-1` is unrelated here; vision analysis uses a chat vision model (`gpt-4o-mini`).
- Credentials stay server-side; none are present in `.env`, logs, bundles or Git.
