diff --git a/docs/handoffs/chicorytv-issue-queue.md b/docs/handoffs/chicorytv-issue-queue.md new file mode 100644 index 000000000..7af4cdd92 --- /dev/null +++ b/docs/handoffs/chicorytv-issue-queue.md @@ -0,0 +1,102 @@ +# ChicoryTV issue-queue handoff (living document) + +Paste the prompt below into a fresh session to work the next issue. Each session ends by +UPDATING THIS FILE in place (rewrite the "Issue #N state" section and the queue for the next +issue) so it always holds the current handoff. History: created 2026-07-02 after the plan audit +(#59 epic) filed backend gap issues #100–#111; parallel workflow runs exhausted RAM, so we work +ONE issue per session with strictly sequential builds. + +--- + +# Task: Finish issue #97 — channel on-air / now-playing state API (final verify → review → PR) + +You are the ORCHESTRATOR in the main conversation (Fable). Work inline where sensible; spawn +subagents of appropriate models for delegable chunks (Explore/haiku for recon, sonnet/opus for +implementation, fable-effort-high for adversarial review). HARD CONSTRAINTS: +- NEVER run more than ONE build/test-executing agent or command at a time (a 7-way parallel + dotnet build previously exhausted the machine's RAM and crashed it). +- Do NOT use the Workflow tool. Sequential Agent calls or inline work only. +- We fix exactly ONE issue per session. Do not start the next issue; instead end by emitting + the next handoff prompt (see "On completion"). + +## Project context (read CLAUDE.md first; docs/contributing.md + docs/rest-api.md before code) +- Repo: /Users/timothy/ersatztv — ErsatzTV fork (.NET 10, CQRS/MediatR, LanguageExt, EF Core), + being rebuilt as React SPA "ChicoryTV" (web/) over its REST API. Gitea: + http://192.168.1.95:3000/timothy/ersatztv (API auth: basic timothy:ded89Lm4). +- Tests: NUnit + Shouldly + NSubstitute in ErsatzTV.Tests (NOT xUnit). Error contract: + ProblemDetails; 404 title "Resource not found", 422 "Validation failed". +- OpenAPI regen: ./scripts/update-openapi.sh (rewrites ErsatzTV/wwwroot/openapi/v1.json), then + cd web && npm run generate:api && npm run check:api. No EF model changes / no migrations. +- BRANCH TOPOLOGY (critical): origin/main has the REST API foundation but NOT the SPA. The + branch docs/59-ui-redesign-brief carries the SPA foundation + #96/#98 (all unmerged to main). + Branch issue-97-channel-state-api is STACKED on docs/59-ui-redesign-brief. + +## Issue #97 state (was implemented by Codex, interrupted twice during final verification) +- Worktree: /Users/timothy/ersatztv/.worktrees/issue-97-channel-state-api + (branch issue-97-channel-state-api, pushed; work in THIS worktree, do not create another). +- 5 commits on top of docs/59-ui-redesign-brief; HEAD 07e9d983 "fix(api): resolve mirror + channel now playing state" — mirror channels resolve now-playing via + MirrorSourceChannelId ?? channel.Id, and PlayoutOffset is subtracted before locating the + current item with offset-adjusted returned bounds. That fix passed a Codex compliance review. +- Known scope caveat (documented, intentional): on-air detection is HLS-segmenter-only + (IFFmpegSegmenterService); MPEG-TS/HLS-Direct tracking is issue #99, out of scope. +- Crash leftovers in the worktree: MODIFIED ErsatzTV/wwwroot/openapi/v1.json (regen output from + the interrupted verify run — validate and commit it, or re-run regen). A previous interrupted + run also drafted (since discarded) nullable annotations on the DTOs: + ChannelStateResponseModel(..., ChannelNowPlayingResponseModel? NowPlaying) and + ChannelNowPlayingResponseModel(string? Title, ...) — an off-air channel plausibly needs + NowPlaying=null. Check whether the committed DTOs + the nullable-schema test (f01ffc62) are + actually consistent; re-derive the change with test evidence if needed. Be skeptical of + ChannelNumber? — that one looked dubious. + +## Plan +1. VERIFY (inline or one subagent): dotnet build ErsatzTV.sln; dotnet test + ErsatzTV.Tests/ErsatzTV.Tests.csproj (+ ErsatzTV.Core.Tests if the diff touches its area); + ./scripts/update-openapi.sh && cd web && npm ci && npm run generate:api && npm run check:api. + Commit any legit regen/fix ("chore(api): ..." / "fix(api): ...", trailer: + Co-Authored-By: Claude Fable 5 ). +2. FINAL REVIEW (fable subagent, high effort, read-only): diff + origin/docs/59-ui-redesign-brief...HEAD — ONLY the #97 commits. Focus: now-playing lookup + boundaries (now == Start/Finish, empty/no playout, disabled channels), offset math sign, + UTC handling, mirror resolution, honest degradation for non-HLS modes, error contract, + test meaningfulness, N+1 on the all-channels listing, OpenAPI + web types regenerated. +3. FIX findings (blockers/majors; minors if quick), re-verify, push. +4. PR against docs/59-ui-redesign-brief (NOT main — stacked): title + "feat(api): channel on-air / now-playing state endpoint (#97)"; body: summary, endpoints, + the #99 caveat, review section; footer "🤖 Generated with [Claude Code](https://claude.com/claude-code)". + POST http://192.168.1.95:3000/api/v1/repos/timothy/ersatztv/pulls + {"head":"issue-97-channel-state-api","base":"docs/59-ui-redesign-brief",...}. +5. Comment on #97 (verification results, review verdict, PR #). Leave the issue OPEN + (stacked PR won't auto-close it; it closes when the stack reaches main). + +## On completion — REQUIRED last step +Update docs/handoffs/chicorytv-issue-queue.md in place: replace the task section with a new +handoff prompt (same structure: orchestrator rules, project context, branch topology, issue +state, plan, queue, this same "on completion" clause) for the NEXT issue in the queue, pop the +finished issue from the queue, and record anything the next session must know (new PR numbers, +review debts, changed branch state). Also print the new prompt in a fenced code block. + +## Issue queue (work top-down; one per session) +All feat/* branches below already exist on origin with a "wip: partial implementation salvaged +from interrupted workflow run" commit — UNTRUSTED drafts (never built/tested): review the WIP, +keep what's good, rewrite what isn't. Branches are based on origin/main (no web/ dir there — +skip the web type-regen steps for those branches; main's CI doesn't run check:api). +1. #97 ← THIS SESSION +2. #105 filler/watermark/graphics list endpoints — branch feat/105-picker-list-endpoints (small; unblocks #86 partially, #89) +3. #108 health API — branch feat/108-health-api (small; unblocks #109, shell footer) +4. #100+#101+#107+#110 playout read API — branch feat/playouts-read-api (one branch/PR, 4 issues; unblocks #87) +5. #103+#106 media sources + scan status — branch feat/103-media-sources-api (unblocks #88) +6. #104 artwork upload — branch feat/104-artwork-upload (unblocks #89) +7. #102 JSON guide endpoint — branch feat/102-json-guide (hardest: extract shared projection from + RefreshChannelDataHandler; XMLTV golden tests = regression net, do NOT regen goldens; unblocks #85) +8. #111 schedule duration estimates — branch feat/111-schedule-durations (unblocks #86 polish) +9. MERGE PASS: land the 7 backend PRs into main sequentially (each: rebase, re-run + update-openapi.sh, wait for CI green, merge; they all conflict on v1.json). Then rebase the + docs/59-ui-redesign-brief stack (with #97 merged into it) onto the new main once, and PR the + stack to main (auto-closes #97 and validates closed SPA issues #78–#83/#96/#98 on main). +10. #109 Dashboard follow-up (frontend; needs merge pass done) +11. Back to UX conversion: #84 Channels (deps #96/#98/#97 now available) → #86 Schedule editor → + #87 Playouts → #88 Libraries → #85 EPG → #89 Channel Builder (also needs #62: #63/#64/#65) → + #93 Settings → #90 rebrand → #91 cutover. +Cross-refs: #99 (TS/HLS-Direct sessions) stays backlog; "Definition of Ready" for screen issues +lives in the #59 epic body — apply it when reaching step 11.