96a67c7e767e601d9c9f330ce491c0ef2e9bed92
Round four, one Medium, and it lands on the defence rather than the code: the change argued that its residue was acceptable BECAUSE it was accurately disclosed, and the disclosure was wrong within one round. `SHIP-IT) state=success ;;` is valid shell selecting `success`. Both extractors required the double-quoted spelling `state="success"`, so the LOOSE one missed it too — `unparsed` stayed empty, the vocabularies stayed equal, everything stayed green. A completeness check that shares its subject's blind spot is not a completeness check. The bug was structural, not about quoting. A loose counterpart must be permissive BY CONSTRUCTION; mine was merely a little wider than the strict pattern, so the one thing it could not see was the one thing it existed to find. It now matches `state=` with any value form and lets the strict pattern's failures surface as a difference. Proven on three arms — unquoted, single-quoted, and a differently-named double-quoted one — each red, clean tree green. The disclosure is corrected too, and this is the part worth keeping. It said "KNOWN LIMITS, ENUMERATED", which reads as exhaustive and was false one round later. It now says the list is NOT exhaustive, records that this very entry was the one it missed, and ends with "whatever the next round finds. Assume this list is one short." Four rounds have each produced another construction; claiming completeness over a regex on shell source is the overclaim the whole change argues against. Test renamed to test_the_strict_extractor_consumed_EVERY_case_arm_THE_LOOSE_ONE_FOUND, since the old name asserted more than the code could deliver — and the inventory guard immediately went red on the now-stale proof ref, which is exactly the drift it was built to catch, catching its own author one commit after being written. ruff clean, pyright clean, decisions-validate OK, 580 script-tests pass. Refs #774 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.
