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>
103 lines
7.5 KiB
Markdown
103 lines
7.5 KiB
Markdown
# 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](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.
|