115 lines
7.8 KiB
Markdown
115 lines
7.8 KiB
Markdown
# 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 2–3 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 (~150–252). /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.
|