Replace informal implementer workflow with structured 7-step protocol including mandatory root cause analysis for bug fixes. References /done skill for automated enforcement. Part of adversarial-reviewer #260. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.8 KiB
ErsatzTV Fork
Custom IPTV channel server for Jellyfin. Forked from ErsatzTV/ErsatzTV after upstream archival (Feb 2026, v26.3.0). Our fork lives on Gitea.
Architecture
- Language: C# / .NET 10, Blazor Server UI (MudBlazor)
- Pattern: CQRS via MediatR — queries/commands in
ErsatzTV.Application/ - Database: EF Core (SQLite default, MySQL optional) — context in
ErsatzTV.Infrastructure/Data/TvContext.cs - Media: FFmpeg via CliWrap, SkiaSharp for logo generation
- Functional C#: Language Ext (Option, Either monads throughout)
Project Layout
| Project | Role |
|---|---|
ErsatzTV/ |
ASP.NET Core host, Blazor pages, API controllers, DI setup |
ErsatzTV.Application/ |
MediatR handlers (business logic) |
ErsatzTV.Core/ |
Domain entities, interfaces, no infrastructure deps |
ErsatzTV.Infrastructure/ |
EF Core repos, data access |
ErsatzTV.Infrastructure.Sqlite/ |
SQLite-specific implementations |
ErsatzTV.FFmpeg/ |
FFmpeg process wrapper |
ErsatzTV.Scanner/ |
Media library scanning |
Key Files
- M3U generation:
ErsatzTV.Core/Iptv/ChannelPlaylist.cs→ToM3U() - XMLTV generation:
ErsatzTV.Application/Channels/Queries/GetChannelGuideHandler.cs - IPTV controller:
ErsatzTV/Controllers/IptvController.cs—/iptv/*routes - Logo generation:
ErsatzTV.Core/Images/ChannelLogoGenerator.cs - Channel entities:
ErsatzTV.Core/Domain/Channel.cs - DB context:
ErsatzTV.Infrastructure/Data/TvContext.cs
Deployment
- Docker host: jazz (192.168.1.99), container
ersatztv, port 8409 - Config volume:
~/downloadswarm/ersatztv/on jazz →/configin container - SQLite DB:
/config/ersatztv.sqlite3(WAL mode, root-owned) - Image:
ghcr.io/ersatztv/ersatztv:latest(to be replaced with our fork's image)
Development
# Build
dotnet build ErsatzTV.sln
# Run locally (needs FFmpeg in PATH)
dotnet run --project ErsatzTV
# Docker build
docker build -f docker/Dockerfile -t ersatztv:dev .
Conventions
- Follow existing MediatR CQRS pattern for new features
- Domain logic in
ErsatzTV.Core, infrastructure inErsatzTV.Infrastructure - Keep Blazor pages thin — delegate to MediatR handlers
- Test with xUnit (existing test projects)
- Backlog tracked via Gitea Issues
Task Completion Protocol
Every task that closes a Gitea issue MUST complete ALL of these before it is considered done. Use /done <issue> to run through this automatically.
- Root cause (bug fixes / incidents only): Document WHY the problem existed, not just what was changed. If root cause is unknown, say so explicitly and open a follow-up investigation issue. Fixing symptoms without understanding causes creates recurring problems.
- Comment on issues as you work — what you found, what approach you're taking, any deviations from the suggested fix.
- Push changes:
git pushall commits before closing. Usefixes #Nin commit messages to auto-close where appropriate. - Close comment: Add a structured closing comment on the issue covering: what was done, root cause (if applicable), files changed, anything deferred, follow-up issues created, and which docs were updated.
- Close the issue via API or
fixes #Ncommit. Leave open with a comment only if partially addressed. - Update docs: If the change affects operational behavior, update the relevant Obsidian docs (
~/homelab-docs/), MEMORY.md, or CLAUDE.md inline — not as a follow-up. - Reply to reviewer (if from adversarial review): Summary of done/deferred/questions. This triggers the next review cycle.
Project Boundaries
ersatztv OWNS: ErsatzTV fork code (C#/.NET), channel/collection/schedule management, M3U/XMLTV generation, the ErsatzTV skill in server-management.
ersatztv does NOT own:
- Docker compose configs → server-management (
~/downloadswarm/stacks/ersatztv/) - NFS mounts, Ansible, DNS, networking → server-management
- Content sourcing (yt-dlp downloads, Sonarr/Radarr libraries) → media-management (planned)
- Jellyfin skill → server-management (symlinked)
For infrastructure changes (Docker, NFS, ports, Authelia): open an issue in timothy/server-management.
For content/media sourcing questions (what goes into channels, yt-dlp pipelines): open an issue in timothy/media-management once it exists; for now, timothy/server-management.
For plan/audit reviews: open ~/adversarial-reviewer before significant architecture changes.
Full cross-project rules: ~/homelab-docs/Operations/Project Boundaries.md (https://docs.tblindustries.be).
ErsatzTV docs: ~/homelab-docs/Docker/ErsatzTV.md + project-local docs/ (fork strategy, channels, M3U/XMLTV).