Skip to content

Tags: danmunz/docent

Tags

v1.5.0

Toggle v1.5.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Atmosphere triptych — 3 curated picks with variety engine (#76)

* feat: atmosphere triptych — 3 curated picks with variety engine

Replaces single-recommendation Atmosphere modal with a 3-card triptych:

Backend:
- New ATMOSPHERE_PROMPT requesting 3 ranked picks with lateral-thinking guidance
- Recommendation history file (atmosphere_history.json) tracking picks over time
- Inverse-frequency weighted pre-filter samples ~20 candidates, avoiding repeats
- random.shuffle() eliminates insertion-order bias in LLM context
- temperature 0.9 and max_tokens 600 for atmosphere calls only
- Fallback padding ensures 3 recommendations even if LLM returns fewer

Frontend:
- 3-card triptych layout (820px max-width, responsive stack at <=600px)
- First card marked Curators pick with accent top-border
- Staggered reveal animation (150ms intervals)
- Each card: thumbnail, wiki-linked title, curator note, vibe pills, Display button
- Explored N of M counter below cards
- atmosphereRetry() excludes all 3 picks at once
- localStorage persistence with 24h TTL for exclusion list
- closeAtmosphere() no longer clears exclusions

Tests:
- Updated test_full_pipeline for 3-recommendation response schema
- New test_fallback_padding and test_history_persistence
- Updated XSS test for safeTitle variable in pick cards

Closes #65

* fix: deduplicate repeated content_ids in atmosphere recommendations

Track used_ids during LLM result parsing to skip duplicate content_ids
before the padding step. Prevents duplicate cards when the model returns
the same artwork more than once.

Adds test_dedup_repeated_ids to verify 3 unique picks are returned even
when the LLM repeats an ID.

v1.4.0

Toggle v1.4.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #75 from danmunz/fix/prefetch-timeout

v1.3.0

Toggle v1.3.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #74 from danmunz/fix/thumbnail-resilience

fix: thumbnail resilience for large collections (#67)

v1.2.2

Toggle v1.2.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #72 from danmunz/fix/thumbnail-prefetch-throttle

fix: throttle background prefetch and add circuit breaker (#67)

v1.2.1

Toggle v1.2.1's commit message
feat: guided Vision API setup with key validation (#71)

- Add VisionApiError with structured error parsing (extracts Google's
  project-specific enable URL from 403 responses)
- Add POST /api/ai/test-vision endpoint for key validation
- Replace 'Get a key' hint with numbered setup guide (Enable API →
  Create key → Paste) and inline Test button with ✓/✗ feedback
- Propagate vision_error in analysis metadata; show warning in UI
  when Vision silently fails
- Auto-test after saving a new key; support test-before-save flow
- 7 new tests for test-vision endpoint

v1.2.0

Toggle v1.2.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: non-blocking thumbnail prefetch and WebSocket staleness recovery (

…#67)

* test: add diagnostic and reproduction tests for issue #67 thumbnail failures

Add 20 tests across two files that identify and reproduce the root cause
of thumbnail loading failures on large catalogs (500+ artworks).

Root cause: client-server timeout race condition. The server-side
individual fallback (PR #69) takes 53s+ for a batch of 20 IDs when the
TV is struggling, but the frontend's AbortController timeout is 30s.
The client always aborts before receiving the response, never sees the
fallback:true flag, so the progress bar never appears. Three retries
create a ~96s loop ending in 'Tap to retry' on all thumbnails.

test_issue67_diagnosis.py (14 tests):
- Thumbnail key matching with samsungtvws format
- Individual fallback cascade timing (20 TV calls per failed batch)
- TV operation timeout and D2D socket orphaning
- Lock starvation during concurrent fallback operations
- Large catalog scenario (63 TV hits per batch of 20)
- Client timeout race: proves 1 failing ID = 58s worst-case (>30s)

test_reproduce_nitrowolf.py (6 tests):
- Server response exceeds client timeout (53s vs 30s) — matches logs
- Click-to-retry reads from disk cache (2.6ms) — matches user report
- Progress bar never shown (client aborts before response)
- Three-attempt retry loop (96s wall time → 'Tap to retry')
- Concurrent batches compounding the timeout problem
- Settings endpoint blocked by TV lock during fallback

Uses 50x time scaling for fast test execution while preserving the
timing relationships that cause the failures.

Refs: #67, #68, #69

* fix: address Codex review feedback on PR #70

- Mark reproduction test classes with @pytest.mark.xfail(strict=False)
  so a production fix for #67 won't break CI. Tests currently show as
  XPASS (bug still exists); once fixed they'll become XFAIL (expected).

- Replace time.sleep(10) in hanging_fn with threading.Event.wait(2)
  and cancel.set() after assertions, so the executor thread exits
  promptly instead of stalling the suite for 10s.

* fix: non-blocking background prefetch for thumbnail fallback (#67)

Replace synchronous individual thumbnail fallback (which blocked 53s+
for large catalogs) with asyncio.create_task() background prefetch.

Server changes:
- Add _prefetch_thumbnails() background task that fetches thumbnails
  individually via _tv_op() and caches to disk
- Add _thumb_prefetch_in_progress dedup set to avoid redundant fetches
- get_thumbnails_batch() now returns immediately with fallback=True
  and all uncached IDs as missing, spawning background prefetch

Client changes:
- In fallback mode, retry up to 8 times at 3s intervals (vs 3 retries
  with escalating backoff) to pick up newly cached thumbnails

Test updates:
- conftest: reset _thumb_prefetch_in_progress and _tv_lock per test
- test_api_endpoints: verify immediate response + background cache
- test_issue67_diagnosis: update 5 diagnostic tests for new async
  behavior (fast response, background individual calls, disk cache)

* fix: proactively reconnect stale TV WebSocket connections

Samsung Frame WebSocket connections go stale after ~30-60s of
inactivity, causing BrokenPipeError when the user interacts with
the TV after browsing Atmosphere results or other idle periods.

- Track _tv_last_used timestamp, updated after each successful _tv_op
- _ensure_tv_connection checks idle time against TV_CONN_MAX_IDLE (30s)
- Stale connections are proactively closed and reopened instead of
  waiting for BrokenPipeError on the first attempt
- Reset _tv_last_used in test fixtures for proper isolation

* refactor: address PR review comments from Copilot and Codex

- Fix misleading log: 'falling back to individual' → 'scheduling
  background prefetch' (Copilot on server.py:524)
- Fix misleading comment: 'shorter delays' → 'fixed 3s interval'
  with note about normal escalating backoff (Copilot on index.html:2879)
- Replace fixed sleep(0.2) with bounded polling loop in fallback
  tests to avoid CI flakiness (Copilot on test_api_endpoints.py:395,424)
- Rename test_526 → test_524 to match docstring catalog size
  (Copilot on test_issue67_diagnosis.py:281)

v1.1.1

Toggle v1.1.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #69 from danmunz/copilot/diagnose-issue-67-fix

fix: consistent API shape & Set-based progress tracking for thumbnail fallback

v1.1.0

Toggle v1.1.0's commit message
feat: persistent TV connection, /health endpoint, corruption recovery

Closes #67, #57, #63, #19, #47

- Persistent WebSocket connection (11 connections → 2)
- Removed concurrent socket race (_fetch_thumbnails_sync)
- /health endpoint with Docker HEALTHCHECK (503 on errors)
- JSON corruption recovery with _safe_load_json
- Jump-to-current-artwork FAB
- AI settings inline help text

v1.0.1

Toggle v1.0.1's commit message
chore: bump version to 1.0.1

v1.0.0

Toggle v1.0.0's commit message
chore: bump version to 1.0.0