radio: session log update — index UI exposes classifier filters
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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)
|
- **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)
|
- **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)
|
- **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)
|
||||||
|
|||||||
Reference in New Issue
Block a user