From dfd2134cb4dbee42fb4b83c3dfcfbd9a2710f547 Mon Sep 17 00:00:00 2001 From: Timothy Date: Sat, 11 Jul 2026 01:17:26 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20queue=20protocol=20v2=20=E2=80=94=20sta?= =?UTF-8?q?te=20moves=20to=20pinned=20Gitea=20tracker=20#237=20(parallel-s?= =?UTF-8?q?ession=20safe)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- docs/README.md | 5 +- docs/decisions.md | 17 +++ docs/handoffs/chicorytv-issue-queue.md | 162 ++++++++----------------- 3 files changed, 70 insertions(+), 114 deletions(-) diff --git a/docs/README.md b/docs/README.md index 6045edc1b..da13c6c04 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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). diff --git a/docs/decisions.md b/docs/decisions.md index 7dc4f6dec..f46d5d465 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -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). diff --git a/docs/handoffs/chicorytv-issue-queue.md b/docs/handoffs/chicorytv-issue-queue.md index 9d8e61330..6e59dae51 100644 --- a/docs/handoffs/chicorytv-issue-queue.md +++ b/docs/handoffs/chicorytv-issue-queue.md @@ -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.