Files
ersatztv/docs
timothyandClaude Opus 4.8 7a9b30de71
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 6s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m20s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m50s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 3m43s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 6m51s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m26s
fix(api): #269 review fixes — rebase force-write delta so rotation survives a race (Codex F1/F3)
Independent Codex review (reconciled by Fable against a MERGEABLE fork verdict) found
SaveChangesForcingVersion silently DROPPED a pending Version++ under a concurrent
versioned-write race: on DbUpdateConcurrencyException it adopted the DB's current
Version verbatim (original = current = dbVersion), so a bumping sibling committed at
dbVersion instead of dbVersion+1. Net: an editor holding the concurrent writer's ETag
was never invalidated by the sibling's change — the exact lost-update the #253/#269
contract exists to close, lost under the very condition the helper handles.

F1 fix (shared helper, corrects all 25 bumpers incl. the pre-existing Add*ToPlaylist /
schedule-item writers): rebase the pending delta on top of the stored token —
  pendingDelta = current - original; original = dbVersion; current = dbVersion + pendingDelta
Bumpers (delta 1) advance to dbVersion+1; non-bumpers/deletes (delta 0, e.g.
ErasePlayoutHistory) still adopt the stored token unchanged, so RootWriterForceVersionTests
is unaffected. Idempotent across the bounded retry loop.

F3: the force-race tests now assert Version==3 (rebase), not just membership survival;
added the missing Playout force-race+rotate test. Negative-controlled: with the helper
fix reverted, both strengthened tests go red.

F2 (Medium, deferred → #308): two concurrent same-item Add*ToCollection can both pass the
membership check and the loser 500s on the composite-PK violation (DbUpdateException, which
the helper doesn't catch). Pre-existing and narrow (no corruption); doc claims softened to
name it. Filed #308.

Docs: api-conventions §7a + decisions.md prose corrected from "adopt the stored token" to
the rebase semantics.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:40:32 +02:00
..

docs/ — reading order

Purpose: index of docs/ so a fresh contributor/agent knows what to read and in what order. Update this doc in the same PR that adds, removes, or retitles a doc below.

Read in this order at session start:

  1. CLAUDE.md (repo root) — project intro: architecture, layout, dev commands, conventions.
  2. docs/contributing.md — established code patterns (CQRS/MediatR, LanguageExt, the ChicoryTV SPA, EF Core dual-provider migrations, FFmpeg pipeline, analyzers, testing). Read before any non-trivial change.
  3. docs/domain-model.md — what the app IS: entity glossary, channel→playout→schedule/block concept map, where each concept is edited in the SPA.
  4. docs/api-conventions.md — checklist for adding/changing a /api/* endpoint (controllers, DTOs, error mapping, auth, OpenAPI regen, tests).
  5. docs/spa-conventions.md — playbook for adding a screen to the ChicoryTV React SPA.
  6. docs/e2e-local.md (+ scripts/e2e-local.sh) — how to run a live local instance for manual or Playwright-MCP verification.
  7. docs/testing.md — testing map: what each *.Tests project / web suite covers, golden-file nets, the timezone-independence rule, how to run subsets, the per-PR verification gate.
  8. docs/blazor-route-parity.md — historical record of the completed #91 phase (b) cutover: the Blazor Server UI is removed and every legacy route now 302-redirects to its SPA equivalent (or falls through to the catch-all → /app). Read it for the full legacy→SPA route inventory.
  9. docs/decisions.md — append-only "why" log. Check here before challenging an existing convention.
  10. docs/ci-cd.md — build/test/release pipeline, versioning, dependency management.

Also present in docs/:

  • docs/rest-api.md — REST API design doc for ersatztv#2 (goals, conventions, per-slice plan). Largely superseded day-to-day by docs/api-conventions.md; read this for the original rationale.
  • docs/channels.md — Channel entity field reference.
  • docs/m3u-xmltv.md — M3U/XMLTV generation overview (ChannelPlaylist, GetChannelGuideHandler).
  • docs/fork-strategy.md — divergence policy vs upstream ErsatzTV.
  • docs/design-sync.md — Claude Design ↔ repo screen workflow (#92).
  • 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 — 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).