docs: add product direction plans (import, rationale, availability state)

This commit is contained in:
2026-06-26 19:24:11 +02:00
parent 17a65c4926
commit b2f00e879a
3 changed files with 102 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
---
finding: "Add watchlist import / restore"
catalog: "Direction"
impact: "Local-first users can export watchlist state but cannot round-trip it into a new install or after data loss."
base_commit: "0d31d46"
---
## Effort
M - server-side CSV parsing, validation, UI, and service tests.
## Risk
MED - import needs careful duplicate handling, status validation, and partial-failure reporting.
## Confidence
HIGH - export exists and the inverse capability is missing.
## Evidence
- `templates/watchlist.gohtml:18` exposes an “Export to CSV” action.
- `static/watchlist.ts:317-343` implements CSV export from rendered watchlist rows.
- `internal/watchlist/handler.go:21-25` registers update, delete, continue-watching delete, and page routes, but no import route.
## Resolution Approach
Treat this as a product/design implementation plan, not a bug fix. Define the import contract to match the existing export columns: `mal_id`, `title`, `status`, and `updated_at`. The server should validate `mal_id` and supported status values, ignore or display title only as user context, and decide whether `updated_at` is informational or preserved.
Prefer a dry-run or preview step before mutation. The preview should report valid rows, duplicates, unknown statuses, malformed IDs, and rows that would update existing entries. The final apply step should upsert valid watchlist entries for the current authenticated user and return row-level results.
Add service and handler tests for valid import, duplicate rows, invalid statuses, malformed CSV, empty files, and partial success. Keep import scoped to watchlist entries; do not attempt to restore playback progress or continue-watching state unless a separate plan expands the export schema.
Verify with `go test ./internal/watchlist ./...`, `bunx tsc -p tsconfig.json --noEmit`, and `bun run lint:ts` if frontend UI is added.

View File

@@ -0,0 +1,34 @@
---
finding: "Surface recommendation rationale"
catalog: "Direction"
impact: "Recommendation results would be more trustworthy if the UI explained why each title was picked."
base_commit: "0d31d46"
---
## Effort
M - shape rationale data and render compact UI without changing ranking.
## Risk
LOW - this can be presentation-only if ranking is left unchanged.
## Confidence
HIGH - the recommender computes interpretable signals that are not currently shown.
## Evidence
- `internal/anime/recommendations/profile.go:64-101` builds a taste profile from genres, themes, studios, demographics, airing preference, and recency.
- `internal/anime/recommendations/types.go:21-28` stores match counts for recommendation candidates.
- `templates/top_picks.gohtml:22-25` renders only anime cards for Top Picks.
## Resolution Approach
Extend the recommendation result view model with concise, user-readable rationale. Keep ranking unchanged for the first iteration. Examples of acceptable rationale are matched genre/theme/studio badges, “similar to titles in your watchlist,” or “because you watch recent airing shows,” but exact copy should be generated from data already computed by the engine.
Avoid exposing raw scores or overly technical terms. The UI should stay compact enough for card grids and the home carousel. If space is constrained, start with the full `/top-picks` page and leave the home carousel unchanged.
Add recommendation tests that assert rationale is produced for candidates with genre/theme/studio/demographic matches and omitted gracefully when signals are weak. Add template tests or snapshots only if the repo already uses that pattern for similar UI.
Verify with `go test ./internal/anime/... ./templates` and `bunx tsc -p tsconfig.json --noEmit` if any TypeScript changes are needed.

View File

@@ -0,0 +1,34 @@
---
finding: "Expose episode availability freshness / retry state"
catalog: "Direction"
impact: "Users cannot see stale, retrying, or failed episode availability state even though the app tracks it."
base_commit: "0d31d46"
---
## Effort
M/L - scope depends on whether this is a small per-title detail or a broader maintenance page.
## Risk
MED - exposing provider/cache internals can clutter UI or confuse users if wording is too technical.
## Confidence
MED - the data exists, but product shape needs maintainer judgment.
## Evidence
- `internal/episodes/worker.go:12-31` refreshes due episode availability in the background.
- `internal/episodes/service/cache_store.go:50-65` stores next refresh, retry window, last attempt/success, failure count, and last error metadata through query parameters.
- `templates/components/anime_episode_count.gohtml` currently collapses availability to a compact episode/audio label.
## Resolution Approach
Start with the smallest useful user-facing surface: a per-title availability status detail near the existing episode-count/audio label. Show human-readable freshness such as last refreshed, next refresh, retrying soon, or temporarily unavailable. Avoid exposing raw provider errors unless they are sanitized and clearly useful.
Consider adding an authenticated manual refresh action only after the read-only status is useful. Manual refresh should be rate-limited or guarded to avoid hammering providers.
Add service/view-model tests that map cache metadata to user-facing states. Add template tests for fresh, stale, retrying, and failed states. If this becomes a maintenance page instead, split that into a separate design plan before implementation.
Verify with `go test ./internal/episodes/... ./templates ./...` and relevant lint/typecheck commands if UI scripts are added.