Files
ersatztv/docs/handoffs/chicorytv-issue-queue.md
T
timothyandClaude Fable 5 2362850559
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m41s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m4s
docs: post-cutover housekeeping — dep PRs #61/#132 merged, #21/#48/#49/#131 closed, #76 rebased, prod v26.5.0 verified; next prompt = parity #147/#146/#140
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 12:01:07 +02:00

7.8 KiB
Raw Blame History

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) and all SPA screens (#84#89, #93, #109), the rebrand (#90) and the cutover root-flip (#91 phase a, PR #148) are MERGED. v26.5.0 tagged + DEPLOYED to prod 2026-07-07 (verified live: image :26.5.0, / 302→/app, ChicoryTV title, /api/version 26.5.0, M3U serving). Blazor removal (#91 phase b) is blocked on parity issues #140#147.

Session state (2026-07-07, post-housekeeping): main = 7e5a6b75 (+ this doc commit). Housekeeping session did:

  • Dep batch: PR #61 (BlazorSortable 6.0.2 + CliWrap 3.10.2 + Dapper 2.1.79, rebased) and PR #132 (EFProfiler.Appender 6.0.6053, rebased) MERGED; #21/#48/#49 closed as superseded by #61; #131 (Scriban 7.2.0) closed obsolete — main already has Scriban 7.2.5 (47c3c3b5).
  • MCP PR #76 (#58): rebased onto main (clean, purely additive ErsatzTV.Mcp project), 12 tests green locally, pushed (head d1c04030). Still OPEN — needs a content refresh against the full API surface before merge, plus review.
  • Filed #149: CI flake — migrations job MySQL service publishes fixed host port 3306:3306, so two concurrent runs collide ("port is already allocated"). Fix = drop the ports: mapping (job connects via Server=mysql service name); verify MySql drift/apply still passes.
  • Worktrees: removed issue-91-cutover; .worktrees/deps was this session's scratch (remove it). .worktrees/parity-147 exists (branch feat/147-classic-ui-link off 1cf4a7a9, web/ npm ci already done) — rebase onto current main and use it for #147.
  • PARITY NOT STARTED — recon done though; facts baked into the prompt below.

Lessons for all remaining prompts (accumulated):

  • The main checkout (/Users/timothy/ersatztv) sits on the STALE docs/59-ui-redesign-brief branch. NEVER recon/edit there — point subagents at a worktree pinned to origin/main, or they report placeholders that no longer exist (this bit a recon agent on 2026-07-07).
  • Gitea 1.24 has no rerun-run API; retrigger CI with an empty commit. Runs on the single runner queue mostly sequentially; concurrent migration jobs collide on port 3306 until #149 lands.
  • DTO records in ErsatzTV.Core/Api MUST get file-scoped #nullable enable (else OpenAPI emits ["null","string"] and SPA typegen degrades). ErsatzTV.Application has NO nullable context — string? there trips CS8632.
  • NSubstitute + ConfigElementKey: keys are fresh instances per access — stub with Arg.Any<ConfigElementKey>() disambiguated by the generic <T>.
  • Option<T>.ToNullable() doesn't exist; use MatchUnsafe(v => (T?)v, () => null).
  • ./scripts/update-openapi.sh needs a prior normal dotnet build ErsatzTV/ErsatzTV.csproj.
  • Id-taking child-collection GETs 404 on unknown parent via pre-check + ApiResults + an OpenApiErrorResponseContractTests [TestCase] entry.
  • Backlog nits: pageSize unclamped on paged endpoints; artwork content-type trusted (#66); GET /api/guide runs the full 21-include eager-load per channel per request; fillerKind almost always None in JSON guide (merged into adjacent programmes).

PROMPT — Parity kickoff: #147 escape hatch → #146 channel edit → #140 collections

You are Fable, the ORCHESTRATOR in the main Claude Code session (Claude Code only). Fable is EXPENSIVE: delegate (recon → Explore/haiku; mechanical → sonnet; judgment-heavy code → opus; fable forks for review). Read CLAUDE.md + the Lessons above first.

HARD CONSTRAINTS:

  • Work in worktrees off origin/main; NEVER touch /Users/timothy/ersatztv (stale branch). .worktrees/parity-147 exists (npm ci done) — rebase feat/147-classic-ui-link onto origin/main first. cd web && npm ci in any NEW worktree.
  • Max 23 concurrent builds; ONE dotnet build at a time. NEVER set ETV_UPDATE_GOLDENS.
  • Merge consent in-conversation per PR. CI reruns = empty commit (no rerun API).
  • Live-E2E new screens per the #93 recipe (curl localhost, NOT 127.0.0.1 — host guard; wait for "Done migrating search index").

Recon facts (2026-07-07, verified against main)

  • Routing: web/src/App.tsx (~150252). /app/collections renders PlaceholderScreen (App.tsx ~2776). Manual pushState routing, no router lib.
  • #147: web/src/screens/SettingsScreen.tsx, System pane About card (~852) is the natural home for a "Classic UI" link to /system/health; reuse the existing LegacyCallout component (ExternalLink icon + "Legacy UI" badge, used by the Media sources card ~840). Remove again in #91 phase (b).
  • #146: Channels screen edit pencil already navigates navigateToPath(/app/new-channel?edit=${channel.id}) (App.tsx ~1216) but web/src/builder/ChannelBuilder.tsx never reads query params → dead-end. Backend ready: GET /api/channels/{id} → full ChannelViewModel; PUT /api/channels/{id} takes UpdateChannelRequest (ChannelController.cs). Issue #146 also covers /channels/numbers bulk renumbering — bulkRenumberChannels already exists in web/src/api/channels.ts (check what UI exposes it). Decide: hydrate the builder for edit vs a dedicated edit view — the builder's lineup model (from-lineup composite create) does NOT map 1:1 onto editing an existing channel's 30+ settings; a form-style edit view calling PUT may be the honest shape.
  • #140: manual + smart collections have FULL API CRUD (CollectionController incl. items add/remove; SmartCollectionController). NO API exists for multi-collections, playlists, rerun collections → those need backend gap issues/endpoints for full Blazor parity (/media/multi-collections, /media/playlists, /media/rerun-collections). SPA has getCollections()/getSmartCollections() in web/src/api/schedules.ts (no collections.ts yet). Tests: Vitest + testing-library; App.test.tsx mocks fetch by path (mockDashboardApi).

Task (in order)

  1. #147 [small, sonnet]: Classic UI link in Settings → System About card (+ optional "opens in ChicoryTV" cue on migrated Blazor sidebar links, per the issue). Vitest coverage. PR, CI, consent, merge.
  2. #146 [opus]: channel edit path. Scope call first (builder hydration vs edit form — recommend and confirm in an issue comment), then implement + tests + live E2E. Include or explicitly defer /channels/numbers with an issue comment. PR, consent, merge.
  3. #140 [opus, biggest]: collections screen for manual + smart collections (list/create/ edit/delete/items). File follow-up issues for multi/playlist/rerun API gaps and cover those types read-only if feasible (they surface in GET /api/collections by CollectionType). PR, consent, merge.
  4. Adversarial review fork over each PR diff before asking merge consent.
  5. Update THIS handoff: merged PRs + main SHA, pop done items, next prompt = remaining parity (#141#145). Commit to main. Print the next prompt in a fenced block.

Issue queue (work top-down)

  1. #147 SPA escape-hatch link (tiny) ← PROMPT above
  2. #146 channel edit + /channels/numbers (blocker for #91b)
  3. #140 collections management (biggest gap; spawns multi/playlist/rerun API follow-ups)
  4. #141#145 remaining parity gaps (media browse/search, trakt, filler, watermarks, ffmpeg profiles, blocks/decos/templates, playout editors, logs, troubleshooting — see each issue)
  5. #91 phase (b): remove Blazor once #140#147 close; also remove the #147 link then.
  6. MCP PR #76 (#58): refresh tool catalog against the full API surface, review, merge.
  7. #149 CI flake (migrations job host-port collision) — small, slot into any session. Cross-refs: #99 (TS/HLS-Direct sessions) stays backlog. Done this pass: dep PRs #61/#132 merged; #21/#48/#49/#131 closed; prod verified on v26.5.0.