Files
ersatztv/docs/handoffs/chicorytv-issue-queue.md
T
timothyandClaude Fable 5 3e44947597 docs: add ChicoryTV issue-queue handoff (one issue per session)
Living handoff document driving the sequential backend-gap work
(#97, #100-#111, merge pass, then UX screens). Each session works
one queue item and rewrites this file for the next.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:31:22 +02:00

7.5 KiB
Raw Blame History

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 noreply@anthropic.com).
  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". 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.