Adds docs/README.md (index), api-conventions.md, spa-conventions.md, e2e-local.md + scripts/e2e-local.sh, blazor-route-parity.md (#91 phase-b tracker), domain-model.md, decisions.md. Rule (CLAUDE.md): read these at session start instead of re-recon; update in the same PR that changes a convention/route/decision. Part 2 = #185. Handoff: #180/#141/#158/#161 closed (PRs #181/#182/#183); #145 playback-only; #91 readiness plan posted; next prompt = #185 + quick wins + #155/#151/#152/#153. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
140 lines
9.3 KiB
Markdown
140 lines
9.3 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), all SPA screens (#84–#89, #93, #109), the rebrand (#90),
|
||
the cutover root-flip (#91 phase a), parity pass 2 (#140/#142/#143/#146/#147), the FULL
|
||
scheduling parity #144/#162 (PRs #170–#175/#179), and the media/troubleshooting parity
|
||
#141/#161 + #158 + #180 (PRs #181/#182/#183) are MERGED. v26.5.0 deployed to prod
|
||
2026-07-07. Blazor removal (#91 phase b) is now gated ONLY on: #151/#152 (multi/rerun
|
||
collection APIs), #153/#155 (playlists + collection-items depth), and #145's last item
|
||
(playback troubleshooting).
|
||
|
||
**Session state (2026-07-07 night, parity endgame session)**: main = dbda2d89 + this docs
|
||
commit; all pre+post-merge CI green through PR #183. This session merged THREE PRs:
|
||
- PR #181 → #180 CLOSED: library-picker artwork fixed at the ROOT (API now returns rooted
|
||
/artwork/... URLs — Blazor-relative values never worked in the SPA), season tiles
|
||
replaced by a show-tile "Seasons" drill-in (browse `parentId` param), collections
|
||
add-items dialog got media-kind filter chips.
|
||
- PR #182 → #158 CLOSED (#145 now playback-only): block-playout history endpoints
|
||
(GET /api/playouts/{id}/blocks, .../blocks/{blockId}/history paged, /api/playouts/
|
||
history/{id} decode-by-row-id) + POST /api/troubleshoot/validate-schedule (YAML in
|
||
body); SPA screens /app/troubleshooting/blocks + /app/troubleshooting/yaml.
|
||
- PR #183 → #141 + #161 CLOSED: detail endpoints GET /api/{movies,shows,seasons,artists}/
|
||
{id} + /api/media-items/{id}/info; image folders GET/PUT; browse parentId extended to
|
||
Episode + MusicVideo; SPA detail pages /app/media/{kind}/{id} via MediaRouteScreen
|
||
(sub-path ownership) + /app/media/images/browser; shared ApiArtwork.Root() helper.
|
||
- **ONBOARDING DOCS LANDED (part 1)**: docs/README.md (index), api-conventions.md,
|
||
spa-conventions.md, e2e-local.md + scripts/e2e-local.sh, blazor-route-parity.md (the
|
||
#91 tracker), domain-model.md, decisions.md. RULE (also in CLAUDE.md + memory): read
|
||
these at session start INSTEAD of re-recon; update them in the same PR that changes a
|
||
convention/route/decision. Part 2 (testing map + generated endpoint index) = **#185,
|
||
HIGH PRIORITY next session**.
|
||
- New issues: #184 (ApiControllerSecurityTests registry drifted — 9 controllers unlisted,
|
||
2 with mutating verbs; fix = assembly scanning, S), #185 (docs part 2, S+S).
|
||
- #91 phase (b) readiness plan POSTED on #91 (comment 2026-07-07): gates = #145 playback
|
||
+ #151 + #152 + #153/#155; then Step 1 redirect sweep [S, independent — can ship any
|
||
session], Step 2 Blazor deletion [M-L, own session], Step 3 verification+docs. ~105
|
||
routes are SPA-ready awaiting redirects; only 4 functional areas remain Blazor-only.
|
||
- Tests: ErsatzTV.Tests 828, Core.Tests 493 (+1 skip), Architecture 5, web 330. All PRs:
|
||
fork adversarial review + live browser E2E + CI before merge; all three reviews came
|
||
back with zero must-fixes.
|
||
- Worktrees: fix-180 / feat-145 / feat-141 / wrapup can all be removed (work merged).
|
||
|
||
**Lessons for all remaining prompts** (pruned — conventions moved to docs/):
|
||
- READ docs/README.md → the convention docs FIRST; point recon/implementer agents at
|
||
specific doc sections instead of re-explaining. Only recon what the docs don't cover.
|
||
- The main checkout (/Users/timothy/ersatztv) sits on a STALE branch. NEVER recon/edit
|
||
there — worktrees off origin/main only; `cd web && npm ci` (or copy node_modules from a
|
||
sibling worktree) in NEW worktrees.
|
||
- PR routine (unchanged, works): worktree → implement (opus agent; give it doc pointers +
|
||
exact facts) → merge origin/main into branch before PR (v1.json/v1.d.ts conflicts →
|
||
take either side, REGENERATE, full test pass; sonnet reconcile agent) → push, PR →
|
||
fork adversarial review + sonnet live-E2E in parallel → CI green → merge (consent: ask
|
||
in-conversation; the 2026-07-07 "pre-approved when issue complete and tests green"
|
||
grant was SESSION-SCOPED — re-ask each new session) → structured close comments per
|
||
CLAUDE.md protocol.
|
||
- Live E2E: scripts/e2e-local.sh automates launch (wwwroot+app copy, fresh scratch
|
||
ETV_CONFIG_FOLDER, waits for "Done migrating search index"); single port 8409 for
|
||
UI+API; mutating verbs need no API key locally; seed a Block playout via POST
|
||
/api/playouts {"channelId":N,"scheduleKind":"Block"}. Playwright MCP screenshots land
|
||
in the repo-root cwd — tolerated.
|
||
- Gitea 1.24: no rerun-run API — retrigger CI with an empty commit; poll by commit:
|
||
/api/v1/repos/timothy/ersatztv/commits/{sha}/status.
|
||
- A subagent died mid-run once (connection error): resume via SendMessage ("check git
|
||
status/log, finish verification, commit") — its context survives, work isn't lost.
|
||
- Backlog nits: #172 (API hardening incl. negative-id "(none)" rows), #163/#164, #176
|
||
(PseudoTV-style creation, post-phase-b), #177/#178 (Jellyfin), #66. Quick wins still
|
||
open: Trakt matched-items link → /app/search; parallelize GET /api/search
|
||
(Task.WhenAll); dead header "New Group" primaryAction sweep.
|
||
|
||
---
|
||
|
||
# PROMPT — Docs part 2 + quick wins, then collections/playlists API gaps (#155 → #151/#152 → #153) toward #91 phase (b)
|
||
|
||
You are Fable, the ORCHESTRATOR in the main Claude Code session (Claude Code only). Fable is
|
||
EXPENSIVE: delegate (recon → Explore/haiku; mechanical/reconciles → sonnet; judgment-heavy
|
||
code → opus; fable forks for review). FIRST read CLAUDE.md, docs/README.md and the convention
|
||
docs it indexes, and the Lessons above.
|
||
|
||
HARD CONSTRAINTS:
|
||
- Work in worktrees off origin/main; NEVER touch /Users/timothy/ersatztv (stale branch).
|
||
`cd web && npm ci` in any NEW worktree (or copy node_modules from a sibling worktree).
|
||
- Max 2–3 concurrent builds; ONE dotnet build at a time. NEVER set ETV_UPDATE_GOLDENS.
|
||
- Merge consent in-conversation per PR (user may pre-approve the session; last session's
|
||
pre-approval does NOT carry over). CI reruns = empty commit.
|
||
- Live-E2E new screens via scripts/e2e-local.sh (see docs/e2e-local.md).
|
||
- Adversarial review fork over each PR diff before merge; apply should-fixes.
|
||
- Convention docs: read at start; any PR that changes a convention, migrates a route, or
|
||
reverses a decision updates the relevant doc IN THE SAME PR.
|
||
|
||
## Known facts (2026-07-07 night — re-verify cheaply)
|
||
- main = post-#183 + docs commit: #141/#158/#161/#162/#144/#180 all CLOSED. #145 open
|
||
(playback troubleshooting ONLY — L, own session, do LAST). Phase (b) gates + removal
|
||
plan live on #91.
|
||
- #185 (HIGH, S+S): docs/testing.md consolidation + scripts/generate-endpoint-index
|
||
hooked into update-openapi.sh (docs/endpoint-index.md, generated not hand-written).
|
||
- #184 (S): ApiControllerSecurityTests → assembly scanning (9 controllers unlisted;
|
||
ArtworkUploadController POST + ChannelTemplateController POST/PUT/DELETE unchecked).
|
||
- #155 (S): GET /api/collections/{id}/items missing (+ POST items 500 fix noted in the
|
||
issue) — smallest gap, unblocks collections depth; coordinate DTO with #141's paged
|
||
shapes.
|
||
- #151/#152 (M, mirror each other): multi-collections + rerun-collections REST CRUD +
|
||
SPA editors (Blazor refs: MultiCollections/MultiCollectionEditor.razor,
|
||
RerunCollections/RerunCollectionEditor.razor). One session together.
|
||
- #153 (M): playlists/playlist-groups CRUD (PlaylistController is GET-only today) + SPA
|
||
playlist editing to Blazor PlaylistEditor.razor depth.
|
||
- Quick wins interleavable: Trakt link swap, GET /api/search parallelization, dead "New
|
||
Group" primaryAction sweep.
|
||
|
||
## Task
|
||
1. Verify main green (post-#183 merge + docs commit).
|
||
2. #185 docs part 2 [S+S] — small PR, no browser E2E needed (docs+script only; the
|
||
endpoint-index generation must run in the PR to prove it works).
|
||
3. Quick-wins PR [S]: #184 registry scan + Trakt link swap + search parallelization +
|
||
"New Group" sweep (one branch, one review pass; E2E only the UI-visible bits).
|
||
4. #155 [S] then #151/#152 [M] (one combined PR is fine if clean) — full PR routine each.
|
||
Comment/close issues per the CLAUDE.md protocol; update docs/blazor-route-parity.md
|
||
rows in the same PRs.
|
||
5. #153 [M] if capacity remains — else queue it top for next session.
|
||
6. Do NOT start #145 playback troubleshooting late in the session — own session.
|
||
7. Update THIS handoff (state, lessons, next prompt), commit to main, print next prompt
|
||
in a fenced block.
|
||
|
||
---
|
||
|
||
## Issue queue (work top-down)
|
||
1. #185 onboarding docs part 2: testing map + generated endpoint index [S+S, HIGH]
|
||
2. Quick wins: #184 security-registry scan + Trakt link → /app/search + parallelize
|
||
GET /api/search + dead "New Group" sweep [S combined]
|
||
3. #155 GET /api/collections/{id}/items (+POST fix) [S]
|
||
4. #151 + #152 multi/rerun collections API + SPA editors [M, mirror pair]
|
||
5. #153 playlists CRUD + SPA editor depth [M]
|
||
6. #145 playback troubleshooting screen [L, OWN SESSION]
|
||
7. #91 phase (b): Step 1 redirect sweep [S — independent, can ship any session];
|
||
Steps 2–3 Blazor deletion + verification [M-L, own session, after gates close]
|
||
Backlog (non-blocking): #172 API hardening, #163 playout goldens, #164 health UX, #176
|
||
PseudoTV-style creation rethink (post-phase-b), #177 Jellyfin music-video metadata, #178
|
||
Jellyfin plugin idea, #66 artwork sniffing.
|