#151/#152 (PR #194) + #153 (PR #195) + #190 (PR #192) merged & closed; next = #145 playback troubleshooting (last gate for #91 phase b). Records the VM-127 runner caveat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.9 KiB
ChicoryTV issue-queue handoff (living document)
Paste the prompt below into a fresh session to work the next item. Each session ends by UPDATING THIS FILE in place (rewrite the state section and the queue for the next item) so it always holds the current handoff. History: created 2026-07-02 after the plan audit (#59 epic); all backend gap issues (#100–#111), all SPA screens (#84–#89, #93, #109), the rebrand (#90), the cutover root-flip (#91 phase a), full scheduling parity (#144/#162), media/troubleshooting parity (#141/#161/#158/#180), onboarding docs (#185), the collections/API-gap batch (#155/#151/#152-backend/#184), and now the multi/rerun/playlist SPA editors (#151/#152 PR #194, #153 PR #195) + CI speedups (#190 PR #192) are MERGED. v26.5.0 in prod; v26.6.0 tagged (awaiting a Komodo pin bump 26.5.0→26.6.0 in server-management to deploy).
Blazor removal (#91 phase b) is now gated ONLY on #145 (playback troubleshooting) — every API gap (#151/#152/#153/#155) is closed.
Session state (2026-07-08, multi/rerun/playlist editors + CI/runner session): main =
81bcfec8. Merged THREE PRs (all fork-reviewed + live-E2E'd + CI-green before merge):
- PR #192 → #190 CLOSED: CI speedups — NuGet package cache (
actions/cache@v4on~/.nuget/packages) in thetest+migrationsjobs, shallow checkout fortest(fetch-depth 1), and a Dockerfile openapi-generator jar-layer reorder. Validated on main's image build. - PR #194 → #151/#152 CLOSED: SPA multi-collection editor (
/app/multi-collections) + rerun-collection editor (/app/rerun-collections), on the PR-#188 REST APIs. MirrorCollectionsScreendialogs + a type→picker→playback-order machinery. Follow-up commit unions an out-of-set stored playback order into the rerun edit-load Select. - PR #195 → #153 CLOSED: playlist CRUD REST API (9 endpoints +
RenamePlaylistGroupcommand + DTOs) and SPA editor (/app/playlists: group tree + item editor with reorder/copy + playout preview). Review hardening: HIGH —PUT /api/playlists/{id}now guardsIsSystem→422 (a system playlist could be renamed/wiped via API); MEDIUMs — system-group rename guard + preview draft validation→422; SPA —Promise.allSettledon the tree load. - New issues filed: #193 (rerun create/update should existence-check
selectedId— a bad id can dangling-FK/500; S, backend-only, still OPEN) and server-management#570 (relocate the Gitea act-runner off bumblebee — DONE by user, runner now on VM 127 on pve4). - Tests on main:
ErsatzTV.Tests913, web 369 (45 files),Core.Tests493(+1 skip), Architecture 5 — all green (verified via the PR runs).
⚠️ CI RUNNER CAVEAT (server-management#570, live): the act-runner moved off bumblebee to
VM 127 — this fixed the prod-contention that was starving Kodi/Jellyfin playback, BUT VM 127
is currently ~4× slower (test job ~19 min cold vs ~4–5 min on bumblebee) and
intermittently fails in a cache-save post-step (the actions/cache tar hangs ~15 min then
kills the job — likely no cache-server configured or insufficient disk on the VM). A docs-only
main push (run #363) failed this way; a workflow_dispatch re-run recovers. So: a red MAIN
push may be a cache-save flake — verify the PR's own run was green before worrying, and re-trigger
a red main via a workflow_dispatch re-run (Gitea 1.24 has no per-run rerun API) rather than
assuming a code fault. Benchmark + two fixes (more vCPU; working cache backend + disk) are on
server-management#570. Until the VM is tuned, budget extra CI wall-clock and expect the odd flake.
Lessons for all remaining prompts (conventions live in docs/; this is workflow lore):
- READ docs/README.md → the convention docs FIRST; point recon/implementer agents at specific doc sections. The convention docs (api/spa/e2e/domain-model/blazor-route-parity) replace re-recon — only recon the task-specific delta (exact merged-API signatures, a Blazor page's field list) that docs deliberately don't freeze.
- The main checkout (/Users/timothy/ersatztv) sits on a STALE branch. NEVER recon/edit there —
worktrees off origin/main only; copy
web/node_modulesfrom the main checkout (cp -R) into NEW web worktrees instead ofnpm ci. Docs-only worktrees need none. Remove worktrees when the PR merges. - Subagent connection drops = the laptop slept, NOT a turn-length problem. The agent's
context AND on-disk work survive. Re-resume with
SendMessage("you dropped when the laptop slept; git status shows X on disk; continue from step N"). This session recovered the #153 backend agent mid-task with zero lost work. - Build/verify locally, then trust it; CI is now the slow+flaky part (VM 127). Full local
passes (dotnet test + web test/lint/build + check:api) + fork review + live-E2E gate a merge;
the runner just confirms. Watch CI by commit status:
/api/v1/repos/timothy/ersatztv/commits/{sha}/status(per-context state). OnlyBuild & test (.NET)is branch-protection-required; the imagebuildjob is skipped on PR runs. - PR routine (works): worktree off origin/main → implement (opus for judgment-heavy, sonnet for
mechanical; give doc pointers + exact facts; mandate the csharp-lsp for C#) → for API changes
build the app project FIRST then
./scripts/update-openapi.sh(regens v1.json + endpoint-index) thennpm run generate:api→ merge origin/main into the branch before PR (resolve route-parity by hand; regen v1.json authoritatively) → full test pass → push, PR → fork adversarial review (SCOPE it "review only; do not answer unrelated questions") + sonnet live-E2E for UI changes (scripts/e2e-local.sh) → apply review should-fixes as follow-up COMMITS (never amend+force — auto-mode blocks the force-push) → CI green → merge (session pre-approval: RE-ASK each new session; this session the user OK'd auto-merge on CI-green + review-clean) → structured close comments per CLAUDE.md protocol. - Combine tightly-coupled API+SPA work (like #153) on ONE branch/PR to save CI cycles — extra relevant now that CI is slow. Do the backend first (it regenerates the TS types the SPA needs).
- Never run TWO committing agents on the same worktree concurrently (races on git state). A read-only review fork alongside an editing agent is fine (the fork reads a committed SHA).
- Reusable API facts: collection-item listings → reuse
PagedLibraryBrowseItemsResponseModel+LibraryBrowseItemMapper; multi/rerun/playlist Application handlers ALL exist (API = controller +DTO+tests). Response DTO records need file-scoped#nullable enable; ErsatzTV.Application has NO nullable context (string?trips CS8632).LanguageExtensions.Applycollapses aNotFoundErrorsubtype into a plainBaseError(→422) — use a controller existence pre-check for a real 404. The in-repoRerunCollectionsScreenis now the canonical mirror for a per-item CollectionType→picker→playback-order editor.
PROMPT — #145 playback troubleshooting (the LAST functional gate for #91 phase b)
You are Fable, the ORCHESTRATOR in the main Claude Code session (Claude Code only). Fable is EXPENSIVE: delegate (recon → Explore/haiku; mechanical/reconciles → sonnet; judgment-heavy code → opus; fable forks for review). FIRST read CLAUDE.md, docs/README.md + the convention docs it indexes, and the Lessons above.
HARD CONSTRAINTS:
- Work in worktrees off origin/main; NEVER touch /Users/timothy/ersatztv (stale). Copy
web/node_modulesfrom the main checkout into NEW web worktrees. - Up to 3 concurrent builds OK; never 5+/wide fan-outs. NEVER set ETV_UPDATE_GOLDENS.
- Subagent drops = laptop sleep; re-resume via SendMessage (work survives).
- Merge consent in-conversation per session (last session's pre-approval does NOT carry over).
- CI is on VM 127 now — slow + occasionally flaky (server-management#570). Verify the PR's own
run was green; a red MAIN push may be a cache-save flake — re-trigger via a
workflow_dispatchre-run, don't assume a code fault. Apply review should-fixes as follow-up commits (no force-push). - Live-E2E new screens via scripts/e2e-local.sh (docs/e2e-local.md). Adversarial review fork per PR diff, SCOPED "review only". Update docs/blazor-route-parity.md rows in the same PR.
Task — #145 playback troubleshooting [L, OWN SESSION]
This is the last gate before #91 phase (b) (Blazor removal). It is LARGE and was deliberately deferred to its own session. The #91 issue body has the phase-(b) checklist.
- RECON [Explore, thorough]: map the legacy Blazor playback-troubleshooting UI (
ErsatzTV/Pages/— the FFmpeg/playback troubleshooting page(s), ffmpeg-troubleshooting report/download, session/HLS diagnostics) and what REST API exists vs is missing for it. Playback/session endpoints may be partial (see #99 TS/HLS-Direct sessions, still backlog). Product a mirror map: Blazor fields/actions → needed API → SPA screen. - Decide the API gap: what troubleshooting/diagnostics endpoints must be added (mirror the controller+DTO+tests pattern; handlers may already exist) before the SPA screen.
- Implement backend (if needed) → SPA screen → live-E2E → full PR routine → close #145.
- Then #91 phase (b): with #145 done, plan/execute the Blazor removal (redirect remaining routes, delete legacy pages, update blazor-route-parity.md). This may itself be a separate session — scope it when #145 lands.
- Consider clearing #193 (rerun existence-check hardening, S backend) as a warm-up/interleave.
- Update THIS handoff, commit to main, print the next prompt in a fenced block.
Known facts (2026-07-08 — re-verify cheaply)
- main = 81bcfec8; ErsatzTV.Tests 913 / web 369 / Core.Tests 493(+1) / Arch 5 all green.
- v26.6.0 tagged (deploy = user bumps Komodo pin). CI runner = VM 127 (slow/flaky, #570).
- Open follow-ups: #193 (rerun existence-check, S). #99 (TS/HLS-Direct sessions) still backlog — likely relevant to #145's diagnostics.
- #91 phase (b) gated ONLY on #145 now.