01de6cbd8b8e81dbab201e637c8d4944b79aa66d
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 21s
PR Gates / Docs update reminder (pull_request) Successful in 14s
PR Gates / decisions lifecycle (pull_request) Successful in 24s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 17s
review-verdict/h10 Awaiting review verdict for 01de6cb
Review verdict / Set review-verdict status (pull_request_target) Successful in 32s
PR Gates / Script tests (pytest) (pull_request) Successful in 4m51s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m36s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m11s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 4m27s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
* is the only wildcard — a rule name's regex metacharacters were live
Found by attacking my own glob fallback from the previous commit before the reviewer got to it, which is the round where this PR's defects have landed every time. The 404 fallback matched a branch-protection rule by substituting `*` into a raw regex, leaving every other metacharacter active. Verified directly: a rule named `main.x` matched the base `mainax`, and `a+b` matched `aab`. The direction is the one that matters — a spurious match to some OTHER rule that happens to require `review-verdict/h10` reports this base as protected when nothing governs it, so a consent gate answers yes on evidence about a different branch. Each literal segment is now escaped before the pattern is assembled, so the wildcard survives and nothing else does. Verified across 11 rule/base pairs: metacharacters are literal, `*` still spans, exact and non-matches unaffected. The regression test needed two goes to stop being vacuous, both times for the same reason the rest of this PR keeps hitting: the stub never 404'd for the new mode, so the run denied earlier via the by-name lookup and never reached the fallback at all. It now goes red against the unescaped predecessor. refs #778 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(754,757): declare graphicsElementIds + padToNearestMinute, and pin every MCP tool to its OpenAPI contract (#760)
fix(754,757): declare graphicsElementIds + padToNearestMinute, and pin every MCP tool to its OpenAPI contract (#760)
ErsatzTV
ErsatzTV lets you transform your media library into a personalized, live TV experience - complete with EPG, channel scheduling, and seamless streaming to all your devices. Rediscover your content, your way.
How It Works
- Install ErsatzTV: Download and set up the server on your system.
- Add Your Media: Connect your media libraries and collections.
- Create Channels: Design and schedule your own live channels.
- Stream Anywhere: Watch on any device with IPTV and EPG support.
Key Features
- Custom channels: Create and schedule your own live TV channels.
- IPTV & EPG: Stream with IPTV and Electronic Program Guide support.
- Hardware Transcoding: High-performance streaming with hardware acceleration (NVENC, QSV, VAAPI, AMF, VideoToolbox)
- Media Server Integration: Connect Plex, Jellyfin, Emby and more.
- Music & Subtitles: Mix music videos and enjoy subtitle support.
- Open Source: Free, open, and community-driven project.
Documentation
Documentation is available at ersatztv.org.
License
This project is inspired by pseudotv-plex and the dizquetv fork and is released under the zlib license.
