# Dogfood QA Report — Pi Multi-FX Pedal

**Target:** http://pedal.local:8080 (RPi live hardware)
**Date:** 2026-06-12
**Scope:** REST API endpoints, HTML pages, Tone3000 search, edge cases vs live Pi
**Tester:** Hermes Agent (automated exploratory QA against real deployment)

---

## Executive Summary

| Severity | Count |
|----------|-------|
| 🔴 Critical | 1 |
| 🟠 High | 2 |
| 🟡 Medium | 1 |
| 🔵 Low | 1 |
| **Total** | **5** |

**Overall Assessment:** The pedal is working! The Pi is online, connected, and serving real data. Dashboard shows live state (volume at 0.33, mono routing, preset system working). Three key issues identified: one critical (dashboard crash when disconnected), one version-sync gap (tonehub aliases not pushed to Pi), and one missing endpoint (`/api/captures`).

---

## Live vs Local — Key Difference

| Check | Local (code test) | Live Pi (pedal.local) |
|-------|-------------------|----------------------|
| Dashboard | 200 | **200 with real data** |
| Connected state | `connected: False` | `connected: True` |
| master_volume | 0.8 (default) | **0.33 (live)** |
| routing_mode | mono | mono, breakpoint 7 |
| Tone3000 search | ✅ Works | ✅ Works |
| Tonehub alias routes | ✅ Work | **404 — not on Pi yet** |

---

## Issues

### Issue #1: Dashboard crashes with 500 when pedal deps not connected 🔴

*(Same as previously reported and fixed locally — needs push to Pi)*

| Field | Value |
|-------|-------|
| **Severity** | 🔴 Critical |
| **Category** | Functional |
| **URL** | `GET /` |

**Description:**
The dashboard template renders fine when pedal deps are connected (tested live — returns 200 with real data), but crashes with HTTP 500 when the pedal is disconnected. Root cause: `_gather_state()` returns only `{"connected": False}` when deps are None, but the template expects full default keys.

**Fix applied locally in `_gather_state()`** — returns full defaults (`master_volume: 0.8`, `routing_mode: "mono"`, etc.) when disconnected.

**Needs:** Commit & push to Pi.

---

### Issue #2: React SPA calls `/api/captures` but backend has no such route 🟠

| Field | Value |
|-------|-------|
| **Severity** | 🟠 High |
| **Category** | Functional |
| **URL** | `GET /api/captures` |

**Description:**
The React SPA (`pi-multifx-pedal-ui/src/App.jsx`) has an API layer that calls `GET /api/captures` to list NAM captures and `POST /api/captures/upload` to upload new ones. However, the backend (`src/web/server.py`) has no `/api/captures` route — returns 404 on both local test and live Pi.

Introduced during "Wire React Knobs to Live API" task — frontend calls were added without building the corresponding backend endpoints. The captures screen in the React UI will silently fail.

---

### Issue #3: Tonehub alias routes not pushed to Pi 🟠

| Field | Value |
|-------|-------|
| **Severity** | 🟠 High |
| **Category** | Deployment |
| **URL** | `GET /api/tonehub/search` |

**Description:**
The alias routes `GET /api/tonehub/search` and `GET /api/tonehub/search/irs` work locally (return Tone3000 search results) but return 404 on the live Pi. These routes were added in an uncommitted change on the local dev machine and were never pushed to Gitea, so the Pi doesn't have them.

The direct routes (`/api/irs/tonedownload/search`, `/api/models/tonedownload/search`) work on the Pi. Only the shorthand aliases are missing.

**Affected routes:**
- `GET /api/tonehub/search` → 404 on Pi (alias for `/api/models/tonedownload/search`)  
- `GET /api/tonehub/search/irs` → 404 on Pi (alias for `/api/irs/tonedownload/search`)

**Needs:** Commit tonehub alias routes + `_gather_state` fix, push to Gitea, pull on Pi, restart server.

---

### Issue #4: `/api/block-params/{fx_type}` returns 200 for unknown types 🟡

| Field | Value |
|-------|-------|
| **Severity** | 🟡 Medium |
| **Category** | Functional |
| **URL** | `GET /api/block-params/99` |

**Description:**
`GET /api/block-params/99` returns 200 with `{"fx_type":"99","params":[]}` instead of 404. The route accepts any string without validating against known FX types. Confirmed on live Pi (same behavior).

---

### Issue #5: Unclosed aiohttp client session warnings 🔵

| Field | Value |
|-------|-------|
| **Severity** | 🔵 Low |
| **Category** | Console |
| **URL** | All Tone3000 routes |

**Description:**
Unclosed aiohttp ClientSession on Tone3000 API calls — resource leak that accumulates warning noise. Same on both local and Pi.

---

## Issues Summary Table

| # | Title | Severity | Type | Status |
|---|-------|----------|------|--------|
| 1 | Dashboard 500 when disconnected | 🔴 Critical | Functional | **Fixed locally** — needs push |
| 2 | React calls `/api/captures`, backend missing | 🟠 High | Functional | Needs new endpoint |
| 3 | Tonehub alias routes 404 on Pi | 🟠 High | Deployment | **Fixed locally** — needs push |
| 4 | block-params 200 for unknown types | 🟡 Medium | Functional | Needs validation |
| 5 | Unclosed aiohttp session | 🔵 Low | Console | Needs cleanup |

## Testing Coverage

### Pages (all 5 on Pi) ✅
| Page | Status | Notes |
|------|--------|-------|
| `GET /` (Dashboard) | 200 ✅ | Live data: master_volume=0.33 |
| `GET /presets` | 200 ✅ | Returns bank 0 / Clean Jazz preset |
| `GET /models` | 200 ✅ | Empty (no models installed) |
| `GET /irs` | 200 ✅ | Empty (no IRs installed) |
| `GET /settings` | 200 ✅ | 15KB, full settings UI |

### API Endpoints on Pi
| Endpoint | Result | Notes |
|----------|--------|-------|
| `GET /api/state` | 200 ✅ | `connected: true` |
| `GET /api/presets` | 200 ✅ | Real presets |
| `GET /api/routing` | 200 ✅ | mono, breakpoint 7 |
| `POST /api/routing` | 200 ✅ | Returns updated routing |
| `GET /api/irs` | 200 ✅ | No IRs loaded |
| `GET /api/models` | 200 ✅ | No models loaded |
| `GET /api/captures` | 404 ❌ | Missing endpoint |
| `GET /api/irs/tonedownload/search` | 200 ✅ | 36 results |
| `GET /api/tonehub/search` | 404 ❌ | Not pushed to Pi |
| `GET /api/tonehub/search/irs` | 404 ❌ | Not pushed to Pi |
| `GET /api/block-params/0` | 200 ✅ | |
| `GET /api/block-params/99` | 200 ⚠️ | Should be 404 |
| `POST /api/bypass/toggle` | 404 ❌ | Check if route exists |
| `POST /api/tuner/toggle` | 404 ❌ | Check if route exists |
| `POST /api/models/tonedownload/install` | 422/500 ⚠️ | Works locally, needs download target |

### Edge Cases
| Test | Result |
|------|--------|
| `GET /nonexistent` | 404 ✅ |
| `GET /api/nonexistent` | 404 ✅ |
| `GET /api/presets/99` | 404 ✅ |

---

## Next Steps

1. **Commit & push** the `_gather_state` fix and tonehub alias routes to Gitea
2. **Pull & restart** on the Pi
3. **Build `/api/captures`** endpoint (list captures + upload)
4. **Add FX type validation** to `GET /api/block-params/{fx_type}`
5. Run retest after fixes are deployed

