docs: queue protocol v2 — state moves to pinned Gitea tracker #237 (parallel-session safe)
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Docs update reminder (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Docs update reminder (push) Has been cancelled
Handoff file reduced to static kickoff prompt + append-only lessons lore; queue/arc/session log live in pinned tracker ersatztv#237 with in-progress claim labels and end-of-session triage. Decision recorded in decisions.md; docs index updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -36,6 +36,7 @@ Also present in `docs/`:
|
||||
- **`docs/endpoint-index.md`** — generated REST endpoint index (method/path/operationId/summary per
|
||||
OpenAPI tag). Do not edit by hand; regenerated by `scripts/generate-endpoint-index.py` /
|
||||
`scripts/update-openapi.sh`.
|
||||
- **`docs/handoffs/chicorytv-issue-queue.md`** — living session-to-session handoff: current queue
|
||||
state, what's next. Check this for what's actively in flight before starting new work.
|
||||
- **`docs/handoffs/chicorytv-issue-queue.md`** — static session kickoff prompt + workflow lore.
|
||||
Queue state (goal, arc, what's in flight/next) lives in the pinned Gitea tracker ersatztv#237
|
||||
— read that, not this file, for current state (protocol: decisions.md 2026-07-11).
|
||||
- **`docs/handoffs/rest-api.md`** — original handoff prompt for kicking off the REST API work (#2).
|
||||
|
||||
@@ -225,3 +225,20 @@ TelevisionShow/TelevisionSeason/Artist per-media-item CollectionTypes and 422s t
|
||||
"Add All" (query-wide) mirrors Blazor's two-step: materialize ids
|
||||
via `GET /api/search/all-items`, then reuse the id-list add endpoints — no query-based add
|
||||
command exists server-side. Issues #208/#209.
|
||||
|
||||
## 2026-07-11 — Queue state lives in the pinned Gitea tracker (#237), not in the handoff file
|
||||
|
||||
With multiple sessions/agents working the repo in parallel, the old protocol — every session
|
||||
wholesale-rewrites `docs/handoffs/chicorytv-issue-queue.md` on main (session state + queue +
|
||||
next-session prompt) — became a last-writer-wins race. New protocol: **volatile queue state
|
||||
moved to Gitea**, which is concurrency-safe by construction. Pinned tracker issue **#237**
|
||||
holds the goal + ordered arc in its body (edited rarely, only on arc changes, re-read before
|
||||
edit) and an append-only session-comment log (fixed template: Closed / Filed / Triage /
|
||||
Arc change / Recommended next). Milestone `Blazor removal (#91 phase b)` + the `review` and
|
||||
`in-progress` labels are the machine-queryable view. Sessions **claim** an issue before working
|
||||
it (`in-progress` label + claim comment; the tiny read→claim race window is accepted, later
|
||||
claimant backs off; stale claims — no commits/comments ~48h — may be taken over with a comment).
|
||||
Every new issue gets an explicit end-of-session triage verdict — gate-blocker (milestone + arc
|
||||
slot) or backlog (label only) — so review findings adjust the queue only through that step and
|
||||
the arc doesn't drift. The handoff file keeps only the **static kickoff prompt** and the
|
||||
**append-only Lessons lore** (per-session prompts are gone; task context lives in issue bodies).
|
||||
|
||||
@@ -1,59 +1,54 @@
|
||||
# ChicoryTV issue-queue handoff (living document)
|
||||
# ChicoryTV issue-queue handoff (static kickoff + workflow lore)
|
||||
|
||||
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), full scheduling parity (#144/#162), media/troubleshooting
|
||||
parity (#141/#161/#158/#180), onboarding docs (#185), the collections/API-gap batch
|
||||
(#155/#151/#152-backend/#184), the multi/rerun/playlist SPA editors (#151/#152 PR #194, #153
|
||||
PR #195), CI speedups (#190 PR #192), #145 playback troubleshooting (PR #199), #198 OpenAPI
|
||||
casing (PR #201) + #193 rerun existence-check (PR #200), the first #91-gate batch
|
||||
#210/#211/#213-partial (PR #214), and the search/media mutation batch #208/#209 (PR #216, shared
|
||||
Add-to layer) are MERGED. **v26.5.0 in prod; v26.6.0 tagged** (awaiting Komodo pin bump in
|
||||
server-management).
|
||||
> **PROTOCOL CHANGED 2026-07-11** (decisions.md entry of same date). Queue state lives in the
|
||||
> **pinned Gitea tracker [ersatztv#237](http://192.168.1.95:3000/timothy/ersatztv/issues/237)**,
|
||||
> not in this file. Do **NOT** write session state, queue order, or next-session prompts here —
|
||||
> sessions ending under the old protocol should append their session comment to #237 instead.
|
||||
> This file holds only the two stable things: the standing kickoff prompt and the workflow lore.
|
||||
> Historical per-session state: `git log` of this file (last state-bearing revision: 8b77d5e7).
|
||||
|
||||
**Session state (2026-07-10, #208/#209 session)**: **#208 + #209 CLOSED via PR #216** (merged
|
||||
c63cadb8). New API surface: `POST /api/playlists/{id}/items` (wraps existing `AddItemsToPlaylist`;
|
||||
handler hardened to reject system playlists — latent Blazor-path gap) and `GET
|
||||
/api/search/all-items` (wraps `QuerySearchIndexAllItems`; Add-All = materialize-then-add, Blazor
|
||||
two-step parity — no query-based add command exists). SPA: shared Add-to layer
|
||||
`web/src/media/addTo/` (Collection dialog w/ inline create, Playlist dialog filtering `isSystem`,
|
||||
Schedule dialog replicating `AddProgramScheduleItem.ForMediaItem` defaults —
|
||||
`addTo/scheduleItem.ts`, SaveAsSmartCollectionDialog, AddToMenu popover) + `MediaPosterCard`
|
||||
`actions` slot; wired into search (card drill-in, per-card add, Select toggle + selection bar,
|
||||
Add All, Save As Smart Collection) and browse/detail (multi-select + select-all-on-page, all four
|
||||
detail screens, per-show Quick/Deep scan gated Plex/Jellyfin/Emby, per-episode Media Info +
|
||||
Troubleshoot, seasons browse kind). **Add-to-schedule is gated to shows/seasons/artists** — the
|
||||
server validator (`ProgramScheduleItemCommandBase.CollectionTypeMustBeValid`) only accepts those
|
||||
per-media-item kinds, matching Blazor's ForMediaItem call sites (found by live E2E: movie adds
|
||||
422'd). Also fixed: portal font bug (nothing set a `body` font; portaled dialogs fell back to
|
||||
Times — `body` rule added), a mount-debounce race (the 300ms query-debounce commit wiped
|
||||
in-progress selections; `lastQueryRef` no-change guard in Search+Browse screens), and the
|
||||
e2e-local.sh stale-asset gotcha (`cp -R` into an existing dir nests + serves the previous run's
|
||||
assets — script now rm-first). New issues: **#217** (add-items handlers validate only 4/10 kinds
|
||||
— pre-existing), **#218** (fresh-DB "Playouts 3" badge + "1 failing" chip). Retro/pre-review
|
||||
issues filed in adversarial-reviewer: #18 (this milestone + #214), #19 (upcoming #207/#212, #202,
|
||||
#91b, #197). #213 remains OPEN (reduced read-only-convenience scope).
|
||||
---
|
||||
|
||||
**Blazor removal (#91 phase b) remaining MUST-FIX gates, in order:**
|
||||
1. **#207 (+#212)** — schedules editor full mutation depth (endpoints exist; needs languages
|
||||
enumeration endpoint shared with #212 channel-editor pickers) ← NEXT (prompt below)
|
||||
2. **#202** — media-source management (write REST API + SPA screens; largest, riskiest)
|
||||
3. **#91 phase (b) removal PR** — pattern redirects + catch-all (#204 plan), blazor-final tag
|
||||
(#205), auth posture note (#206), delete Pages/Shared/ViewModels/Validators + 6 packages
|
||||
(MudBlazor, MediatR.Courier.DependencyInjection, Blazored.FluentValidation, BlazorSortable,
|
||||
Heron.MudCalendar, Chronic.Core). Removal recon is DONE (2026-07-09 gate session): Courier
|
||||
consumers are 100% Blazor (`AddCourier` Startup.cs:394 dies too); the Startup `MapWhen`
|
||||
"blazor" branch (736–795) CO-HOSTS MapControllers/OpenAPI/Scalar — surgical removal only
|
||||
(MapBlazorHub:775, MapFallbackToPage:776, services 379–398); `wwwroot/lib/*`+`css/site.css`
|
||||
are `_Host`-only; check `Locals/*.resx` consumers before deleting; keep `Extensions/`
|
||||
except `NavigationManagerExtensions.cs`.
|
||||
# STANDING KICKOFF PROMPT (paste into a fresh session, unchanged every time)
|
||||
|
||||
You are Fable, the ORCHESTRATOR in the main Claude Code session. Fable is EXPENSIVE: delegate
|
||||
(recon → Explore/haiku; mechanical → sonnet; judgment-heavy → opus; fable forks for review).
|
||||
FIRST read CLAUDE.md, docs/README.md + the convention docs it indexes, and the Lessons below.
|
||||
|
||||
Then work the queue:
|
||||
1. Read the pinned tracker **ersatztv#237** — body = goal + ordered arc + session protocol —
|
||||
and its most recent session comments; list open issues in the `Blazor removal (#91 phase b)`
|
||||
milestone and with the `review` label.
|
||||
2. Pick the top arc item that is open and NOT labeled `in-progress` (or the item the user names).
|
||||
3. **Claim it**: add the `in-progress` label + a "claiming" comment on the issue(s).
|
||||
4. Read the issue bodies (they carry the task context/evidence) and work the item under the
|
||||
HARD CONSTRAINTS below.
|
||||
5. Finish by following the session-end protocol in #237: ONE session comment on the tracker
|
||||
(template in the tracker body, incl. triage verdicts for any new issues), remove your
|
||||
`in-progress` labels, and complete the per-issue Task Completion Protocol from CLAUDE.md.
|
||||
|
||||
HARD CONSTRAINTS:
|
||||
- Work in worktrees off origin/main. Copy web/node_modules from the main checkout.
|
||||
- PARALLELIZE BY DEFAULT: split the task into disjoint slices up front and run 3–4 implementer
|
||||
agents concurrently (recon agents are free — always fan those out). 3–4 concurrent
|
||||
dotnet/npm builds are fine on this Mac (M4, 10 cores, 16 GB); check `uptime` before a big
|
||||
fan-out — if 1-min load > ~6, drop to 2–3. Never 5+ builds (the historic crash was an
|
||||
8–9-way fan-out). NEVER set ETV_UPDATE_GOLDENS.
|
||||
- Never two committing agents on ONE worktree — give each parallel slice its own worktree
|
||||
branched off the feature branch and merge back. Sequence only where a slice genuinely depends
|
||||
on another's output (backend-first narrow, SPA-wide after worked well for #216).
|
||||
- Merge consent in-conversation per session (prior pre-approvals do NOT carry over).
|
||||
- Arm a CI monitor on the PR head sha AT PR-OPEN (commit-status endpoint), not at the end.
|
||||
- Live-E2E via scripts/e2e-local.sh; NEVER exercise download endpoints via browser tabs (curl
|
||||
them). Adversarial review fork per PR diff, SCOPED "review only".
|
||||
|
||||
---
|
||||
|
||||
# Lessons / workflow lore (append-only; conventions live in docs/, this is workflow lore)
|
||||
|
||||
**Lessons for all remaining prompts** (conventions live in docs/; this is workflow lore):
|
||||
- READ docs/README.md → the convention docs FIRST; point recon/implementer agents at specific
|
||||
doc sections. Only recon the task-specific delta.
|
||||
- **blazor-route-parity.md now carries mutation-depth verdicts** (2026-07-09 sweep table at the
|
||||
- **blazor-route-parity.md carries mutation-depth verdicts** (2026-07-09 sweep table at the
|
||||
top of Section 2). A row is only trustworthy if its cluster verdict is PARITY-OK; the sweep
|
||||
evidence lives in the issues #207–#213. Keep the verdict table updated as gates close.
|
||||
- "Screen exists" ≠ parity: the root cause of the false SPA-READY rows was same-session
|
||||
@@ -95,65 +90,8 @@ issues filed in adversarial-reviewer: #18 (this milestone + #214), #19 (upcoming
|
||||
- Live E2E seeding: the local library isn't API-seedable; the #216 E2E agent generated tiny
|
||||
ffmpeg testsrc MKVs + inserted LibraryPath rows via SQL then scanned. Recipe not yet in
|
||||
docs/e2e-local.md — worth adding next time it's needed.
|
||||
|
||||
---
|
||||
|
||||
# PROMPT — #207 + #212: schedules editor mutation depth + channel-editor gaps
|
||||
|
||||
You are Fable, the ORCHESTRATOR in the main Claude Code session. Fable is EXPENSIVE: delegate
|
||||
(recon → Explore/haiku; mechanical → sonnet; judgment-heavy → opus; fable forks for review).
|
||||
FIRST read CLAUDE.md, docs/README.md + the convention docs it indexes, and the Lessons above.
|
||||
|
||||
HARD CONSTRAINTS:
|
||||
- Work in worktrees off origin/main. Copy web/node_modules from the main checkout.
|
||||
- PARALLELIZE BY DEFAULT: split the task into disjoint slices up front and run 3–4 implementer
|
||||
agents concurrently (recon agents are free — always fan those out). 3–4 concurrent
|
||||
dotnet/npm builds are fine on this Mac (M4, 10 cores, 16 GB); check `uptime` before a big
|
||||
fan-out — if 1-min load > ~6, drop to 2–3. Never 5+ builds (the historic crash was an
|
||||
8–9-way fan-out). NEVER set ETV_UPDATE_GOLDENS.
|
||||
- Never two committing agents on ONE worktree — give each parallel slice its own worktree
|
||||
branched off the feature branch and merge back. Sequence only where a slice genuinely depends
|
||||
on another's output (backend-first narrow, SPA-wide after worked well for #216).
|
||||
- Merge consent in-conversation per session (prior pre-approvals do NOT carry over).
|
||||
- Arm a CI monitor on the PR head sha AT PR-OPEN (commit-status endpoint), not at the end.
|
||||
- Live-E2E via scripts/e2e-local.sh; NEVER exercise download endpoints via browser tabs (curl
|
||||
them). Adversarial review fork per PR diff, SCOPED "review only".
|
||||
|
||||
## Task — close the #207 + #212 gates
|
||||
Read issues #207 and #212 (bodies carry the #203-sweep evidence) and adversarial-reviewer #19
|
||||
(pre-review asks). #207 is the screen the false-parity review made an example of: the SPA
|
||||
schedules editor is a near read-only viewer — schedule create/edit/delete missing, every
|
||||
per-item inspector control hard-coded disabled (~35 Blazor fields), add-item is defaults-only —
|
||||
while the REST endpoints already exist and are unused (`PUT /api/schedules/{id}/items` replace,
|
||||
`POST .../items` single-add with the FULL ScheduleItemRequest — see `addTo/scheduleItem.ts` for
|
||||
a working payload builder). Enumerate EVERY Blazor `ScheduleItemsEditor.razor` field and wire it
|
||||
(per-capability diff is the parity standard). #212 channel editor gaps: external logo URL, bare
|
||||
create, and pickers — needs a languages enumeration endpoint shared by both editors (preferred
|
||||
audio/subtitle language pickers); design that endpoint once. Record conventions in
|
||||
decisions.md; full PR routine (OpenAPI regen for any new endpoint; blazor-route-parity verdict
|
||||
rows for the schedules + channel-editor clusters). Comment + close #207/#212 per protocol.
|
||||
|
||||
## On completion — REQUIRED last step
|
||||
Update THIS handoff (pop the done items, promote #202 to next with a fresh prompt), commit to
|
||||
main, print the next prompt in a fenced code block.
|
||||
|
||||
---
|
||||
|
||||
## Issue queue (work top-down)
|
||||
1. **#207 (+#212)** schedules editor depth + channel-editor gaps ← PROMPT above.
|
||||
2. **#202** media-source management (write API + SPA) — largest; pre-review the API design
|
||||
(adversarial-reviewer #19) before building.
|
||||
3. **#91 phase (b)** Blazor removal PR (gate cleared once 1–2 close; #204/#205/#206 fold in;
|
||||
removal recon in session state of the 2026-07-09 entry; adversarial pass mandatory).
|
||||
4. **#197** cold API contract+security review — HARD GATE on #58 close/go-live and MANDATORY
|
||||
before any remote exposure. Inputs: #215, #217, backlog nits.
|
||||
5. Backlog: #215 (API playout mutations skip EntityLocker gating), #217 (add-items validates
|
||||
only 4/10 kinds), #218 (fresh-DB Playouts badge / "1 failing" chip), #213 remainder (logs
|
||||
sort/page-size persistence, block-history page-size/gating, list filters), #99 (TS/HLS-Direct
|
||||
session tracking), #66 (artwork magic-byte sniffing), CI: unpin MySQL service host port 3306
|
||||
(concurrent-run collision), nits (unclamped pageSize, 30 MB bare 413, PlayoutController route
|
||||
Name=/lightweight exists-check, guide 21-include eager-load + fillerKind notes — #85/#102
|
||||
comments), review nits from #216 (last-used-collection memory, detailBrowseItem cast).
|
||||
Cross-refs: v26.6.0 deploy = Komodo pin bump (server-management). Real-transcode E2E of the
|
||||
playback screen: once on the test container (`ersatztv-test` runs `:latest`) — local ffmpeg
|
||||
8.1.2 lacks subtitles/zscale filters.
|
||||
- **Parallel sessions (2026-07-11 protocol)**: claim before working (`in-progress` label — the
|
||||
tiny read→claim race window is accepted; later claimant backs off). Claiming prevents
|
||||
duplicate pickup, NOT overlapping code changes — check the tracker's dependency notes
|
||||
("#234 after #231", "coordinate with #215") before touching shared surfaces. Lessons edits
|
||||
to THIS file: append bullets only, `git pull --rebase` before commit.
|
||||
|
||||
Reference in New Issue
Block a user