From 6239f9fc3a7c8d388ba41104dde4eee4fe3e0f43 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Thu, 30 Apr 2026 06:07:00 -0700 Subject: [PATCH] =?UTF-8?q?radio:=20session=20log=20update=20=E2=80=94=20i?= =?UTF-8?q?ndex=20UI=20exposes=20classifier=20filters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend min_score/exclude_banter wired through to HTML index. Adds score badges (1-5 red->green), topic_class pills, dim styling on banter rows. Live on http://172.16.3.20:8765/. Synced to portable repo. pscp ENOSPC quirk worked around by plink-stdin streaming. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../session-logs/2026-04-30-session.md | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/projects/radio-show/audio-processor/session-logs/2026-04-30-session.md b/projects/radio-show/audio-processor/session-logs/2026-04-30-session.md index 7ad22ae..2cbf6f0 100644 --- a/projects/radio-show/audio-processor/session-logs/2026-04-30-session.md +++ b/projects/radio-show/audio-processor/session-logs/2026-04-30-session.md @@ -250,3 +250,109 @@ The SQLite connection on the container side is `mode=ro` URI — picks up fresh - **Laptop install** is a clone + 2 shell scripts; untested on the actual 5070 (will validate next week) - **ClaudeTools commits:** `5e3b1a2` (this session's main.py change) - **Untested edge cases:** offline behavior (planes, no Tailscale), curl with HTTP/2 to /api/db.sqlite (was tested with HTTP/1.1) + +--- + +## Update: 06:05 — Index UI exposes classifier filters + +User asked to wire the new classifier fields into the search UI. The +backend already supported `min_score` and `exclude_banter` query params +(commit `5e3b1a2`); this update brings them into the HTML index and adds +visible quality indicators on Q/A hits. + +### Update Summary + +Edited `INDEX_HTML` in `server/main.py` to add two filter controls and +score badges. Verified locally via `uvicorn` on `127.0.0.1:8866` against +the classifier-populated DB (no-filter, `min_score=4`, and +`exclude_banter=true` modes all behaved correctly). Hit an unexpected +`No space left on device` from `pscp` despite Jupiter having 37 TB free +on `/mnt/user`; bypassed by streaming the file through plink stdin +(`plink ... "cat > /path" < local_file`). md5 verified byte-identical. +Container rebuilt via `docker compose up -d --build`. Synced the same +`main.py` to the portable repo so the laptop UI stays in sync. + +### What changed in the UI + +- **`min score` select** — values: any, 2+, 3+, 4+, 5. Default `any` to + preserve old search behavior. Filters surface 1,096 mid-and-above + pairs at `3+` or 523 useful pairs at `4+`. +- **`hide banter` checkbox** — when checked, drops the 606 rows with + `is_banter=1`. +- **Score badge per Q/A hit** — small color-coded number (1=red, 5=green) + next to each hit's metadata line. Title attribute shows + `usefulness N/5` on hover. +- **Topic class tag** — small gray pill showing `computer-help`, + `banter`, `off-topic`, `promo`, or `unclear`. +- **Dimmed rendering** — hits with score 1-2 or `is_banter=true` render + at 55% opacity. Visible but visually de-emphasized so good hits stand + out at a glance. +- **`escapeHtml` helper** — defensive XSS guard on `caller_name` and + `title` (transcript-derived strings). + +### Key Decisions (this update) + +- **Default filter "any"** — preserves prior search habits and saved + URLs. Mike opts into filtering when needed rather than being forced + into a curated view. +- **`URLSearchParams` instead of string concat** — only emits + `min_score=` / `exclude_banter=` when non-default, keeping URL bar + clean for the common case. +- **Color-coded badge with both score AND topic tag** — score is + numeric/comparable; topic tag is categorical and explains *why* a + score is what it is. Both together make the classifier's reasoning + visible at a glance without forcing a click. +- **Dim instead of hide for low-quality hits** — keeps everything + visible by default; the filter controls are the explicit "hide" lever. +- **Used `plink "cat > path"` instead of pscp** for the deploy when + pscp failed — faster than diagnosing the underlying scp/shfs issue + and gets the job done deterministically. + +### Problems Encountered (this update) + +- **pscp ENOSPC despite 37 TB free** — `pscp main.py` failed with + `No space left on device` on two retries. df showed 37 TB free on + `/mnt/user`, df -i showed inodes fine. Workaround: + `plink ... "cat > /path/main.py" < local_main.py`. md5sum confirmed + byte-identical post-transfer. Likely Unraid shfs cache-pool churn or + an issue with overwriting an in-use file from inside a container's + mount. Worth understanding eventually but didn't block the deploy. +- **plink output buffering on chained docker commands** — long + `docker compose up -d --build` runs hung from Bash's run_in_background + view (output file stayed empty for minutes). Foreground sync run with + the same command worked instantly. Same pattern observed yesterday. + Workaround: don't background long plink runs; just block. + +### Files Changed (this update) + +| Path | Change | +|---|---| +| `projects/radio-show/audio-processor/server/main.py` | +51 / -4 — INDEX_HTML gained controls + badge styles + topic tag + escapeHtml + dim-class JS rendering | +| `c:/Users/guru/radio-archive-portable/server/main.py` | Same diff, synced from upstream | + +### Commits (this update) + +| Repo | SHA | Branch | +|---|---|---| +| ClaudeTools | `b9af34f` | main | +| radio-archive-portable | `1d6c795` | main | + +### Live verification + +``` +$ curl -s http://172.16.3.20:8765/ | grep -cE "min_score|exclude_banter|badge.s5|topic_class" +10 +$ curl -so /dev/null -w "%{size_download}\n" http://172.16.3.20:8765/ +5757 # was 4040 before +$ curl -s 'http://172.16.3.20:8765/api/search?q=BIOS&kind=qa&min_score=4&limit=2' \ + | python -c "import sys,json; d=json.load(sys.stdin); print('hits:', len(d['qa']))" +hits: 2 # both score=5, topic_class='computer-help' +``` + +### Status at update end + +- UI controls live on http://172.16.3.20:8765/ and on the portable repo +- Backend filters working (verified end-to-end) +- Untouched: HTML still has no per-hit deep-link to `/api/episodes/{id}` + (clicking a hit doesn't navigate). Future enhancement. +- Pending: laptop validation (still next week's task)