2026-03-04 - 2026-09-04
Overview
14 Releases published by 1 user
Published
v26.15.0
Published
v26.14.0
Published
v26.13.0
Published
v26.12.0
Published
v26.11.0
v26.11.0
Published
v26.10.0
v26.10.0
Published
v26.9.0
v26.9.0
Published
v26.8.0
v26.8.0
Published
v26.7.0
v26.7.0
Published
blazor-final
Published
v26.6.0
v26.6.0 — ChicoryTV SPA parity release
Published
v26.5.0
v26.5.0
Published
v26.4.0
v26.4.0
Published
v26.3.1
v26.3.1
385 Pull requests merged by 2 users
Merged
#906 fix(876): sweep session narrative out of hooks, workflows, scripts, tests and code comments; grow the detector to the process corpus
Merged
#905 fix(869,893): re-establish the 1.25.4-dated CI claims on 1.27.1, and settle the page_statuses asymmetry from source
Merged
#903 fix(891): a sourced path is code, so every hook resolves it from its own tree
Merged
#902 fix(855): two glob dialects cannot be canonicalised into one, so model one shape and refuse the rest
Merged
#899 fix(887): the image build builds the SPA and does not test it
Merged
#898 docs(release): record the v26.15.0 release notes
Merged
#897 fix(858,859): a rule the classifier cannot read is not a rule that matches nothing
Merged
#896 fix(870): an empty timeline page is not exhaustion — the walk reads to its cap
Merged
#892 fix(880): an absent recurrence array means unrestricted, an explicit [] is rejected
Merged
#890 fix(849): the verdict gate replaces every unknown state, and proves the clauses that claim to
Merged
#889 fix(845): the verdict writer checks that the gate will honour what it just posted
Merged
#888 docs(853): workflow_dispatch can't be ref-restricted at 1.27.1 — and restricting it would close nothing
Merged
#884 fix(836): never pass --depth to a checkout that may already be complete
Merged
#883 fix(820): derive where Complete<T> is APPLIED, not just what it means
Merged
#882 fix(812): classify the narrative sites by who-benefits; keep the detector's reach
Merged
#879 fix(823,824): a scheduling NULL collection reads as UNRESTRICTED and is guarded at both read sites; the Elastic indexer gets its own mutation proof
Merged
#875 fix(819): derive the SPA page-size guard population from the git index
Merged
#874 fix(809,822): isolate the suite from the production hook-fire log by construction
Merged
#873 fix(803,664): fence the HEAD alias on the PR timeline's pull_push count
Merged
#872 fix(786,789): workflows declare their own per-job metadata; guard populations derive from it
Merged
#871 docs(796): verification code is code under test — and the proof it was claiming an exemption from
Merged
#868 fix(763): page both /statuses/{sha} reads to a validated terminator
Merged
#867 docs(747): re-verify the Gitea 1.25.4-pinned CI claims on 1.27.1, and measure the merge-gate semantics that were source-attested
Merged
#866 probe(747c): DO NOT MERGE
Merged
#864 probe(747a): DO NOT MERGE
Merged
#863 probe(747): absent required status context — DO NOT MERGE
Merged
#862 docs(781,799): re-measure the tooling audit from a derived population, and adopt serena
Merged
#861 fix(787): derive the dropped-step guard's scope, and reconcile its snapshot against the server
Merged
#860 fix(748): declare permissions: on all six workflows, and prove the declaration binds
Merged
#857 fix(744,835): ci-image.yml publishes from main only; guard persist-credentials with no exemption
Merged
#850 fix(742): inherit an h10 verdict only from an allow-listed reviewer
Merged
#847 feat(735): bound the numeric FFmpeg profile fields with a 422, and expose readrate pacing
Merged
#846 fix(788): one declarative H10 verdict vocabulary, derived by both sides
Merged
#843 feat(732): On Now / Next gets a background box, and is on by default
Merged
#842 fix(746): drop the persisted checkout credential; unmask the base-ref fetches
Merged
#841 feat(734): field-level progressive disclosure — shared FieldHelp trigger + panel
Merged
#838 docs(755): ersatztv owns the fork code, media-management owns channel operations
Merged
#834 docs(708): record the live route-2 reproduction against PR #761
Merged
#833 fix(690,758): count the same query a paged handler pages
Merged
#831 fix(721,740): align Auto-Tune proposal rows on a grid; guard AddItemsDialog's async searches
Merged
#827 fix(807): SPA full-replace bodies are built as Complete<T>, with a derived guard over droppable request members
Merged
#826 fix(701): guard SongMetadata's nullable primitive collections at the read site
Merged
#825 fix(772,792): name the missing toolchain image; stop a refusal leaving a verdict comment
Merged
#818 fix(806): guard populations over FILES derive from the git index, not a filesystem walk
Merged
#817 docs: a cancelled job reads as failure where a monitor actually looks
Merged
#815 feat(790): execute every MUTATION grade instead of asserting it
Merged
#814 fix(780): reconcile the ruff gate with #784, merged in parallel
Merged
#813 feat(780): commit a ruff config and enforce it in CI
Merged
#811 feat(784): a doc records the end state — generalize the no-session-narrative rule
Merged
#810 test(785): mutation proofs for the three unproven ranked guards
Merged
#808 feat(779): test the deny path at the production config value, and derive full-replace field lists
Merged
#802 feat(778): name the check-and-use race, and verify the protection the merge gate rests on
Merged
#801 feat(794): witness a fix's test failing BEFORE the fix, and check the claim in CI
Merged
#800 docs(781): re-measure §5.3 from a derived population — the zeros split four ways
Merged
#795 feat(776): every hook reports that it fired, and the report is measured
Merged
#798 fix: the BOM guard was fail-open wherever xxd is not installed
Merged
#793 fix(777): repair both broken LSPs, and name the surface a subagent can actually reach
Merged
#762 chore(deps): update dependency scriban.signed to 7.2.6
Merged
#791 feat(774,775): one rule for guard populations, one for guard proofs — both enforced
Merged
#782 docs(773): root-cause the recurring defect shapes across the full closed-issue corpus
Merged
#770 fix(767): gate the release path on the delimiter ban with a prerequisite job
Merged
#769 docs(720): name all three Komodo stacks and the label-based resolution rule
Merged
#768 fix(756): extend the dropped-step guard to docker-build.yml's required jobs, where a drop is fail-OPEN
Merged
#764 fix(751): a stray expression delimiter in a COMMENT killed the verdict gate — plus the two nil-slice twins and a dead-code guard it hid
Merged
#760 fix(754,757): declare graphicsElementIds + padToNearestMinute, and pin every MCP tool to its OpenAPI contract
Merged
#749 fix(743): make review-verdict/h10 unskippable — disable direct push to main + admin force-merge; fix(719) tag-only push
Merged
#745 fix(697): scope CI's registry credential so head-resolved workflows cannot forge review-verdict/h10
Merged
#741 fix(685): AddItemsDialog resolves by search instead of windowing the whole media-library type
Merged
#739 docs(release): record the v26.14.0 release notes
Merged
#725 fix(674,688): cross-check decision frontmatter against PyYAML; split the ceiling calibration claim
Merged
#737 fix(726): let a lagging realtime input catch up so a sparse bitmap-subtitle stream can't pin it below realtime
Merged
#723 fix(706,707,711): fence the review-verdict write on the timeline retarget count
Merged
#717 chore(deps): update dependency cliwrap to 3.10.4
Merged
#718 chore(deps): update dependency jetbrains.resharper.globaltools to 2025.3.5
Merged
#716 docs(release): record the v26.13.0 release notes
Merged
#714 chore(deps): batch three Renovate patch bumps (supersedes #679, #680, #681)
Merged
#712 chore: ignore .codex/, and stop shipping a plaintext credential in docs
Merged
#710 docs(698): correct the Renovate auto-pass rule in CLAUDE.md
Merged
#705 fix(698): bind the base, constrain the bot exemption by content, re-derive unattributable successes
Merged
#699 fix(672): trigger the verdict gate on pull_request_target scoped to main
Merged
#700 fix(691): guard the nullable SongMetadata.Artists/AlbumArtists at their read sites
Merged
#692 fix(671): resolve rerun-collection selections through one shared include chain
Merged
#687 fix(668): reach accented facet values via a registered Unicode fold on SQLite
Merged
#686 fix(684): key the pageSize guard registry on identity, not source position
Merged
#683 docs(649): narrow the base-ref headline to what the checkout actually binds
Merged
#673 test(649): cover the review-verdict status read and the bot-path guards
Merged
#682 docs: permit subagents explicitly, and make claiming an issue a check rather than a label
Merged
#676 feat(578): artist typeahead covers music-video and song credits; album_artist stops 404ing
Merged
#675 fix(650): two at-cap list truncations, and a completeness guard that keys on the defect
Merged
#678 feat(651): library-browse pickers resolve by search, not a 100-row window
Merged
#666 fix(649): point the ENFORCED review-verdict gate at the shared PR-file enumeration
Merged
#667 fix(632): bind a review verdict to its BASE branch, not only to its head sha
Merged
#658 fix(648): an explicit jq version contract + one shared PR-file enumeration
Merged
#659 docs(ersatztv skill): record the #510 no-logo-no-bug policy and deco seeding recipe
Merged
#657 docs(505): retire the stale "do NOT set QSV on jazz" rule in the ersatztv skill
Merged
#655 fix(510): one watermark resolver for all four attachment points
Merged
#656 fix(644): stop seven SPA list loads truncating silently — one shared pager, bounded media pickers
Merged
#654 fix(505): tonemap QSV HDR through OpenCL — vpp_qsv=tonemap is a silent no-op
Merged
#642 fix(620): signal corpus size per RECORD; the aggregate becomes an untresholded trend
Merged
#637 fix(631): run scripts/tests in CI as its own job, not inside the flake-covered decisions-guard
Merged
#641 fix(621): make an unparseable decision record loud instead of silently invisible
Merged
#646 fix(633): document the 0-based paging contract on the OpenAPI parameters
Merged
#645 fix(634): page the rerun-collection picker to completeness
Merged
#636 fix(629): close six false-opens in the H10 verdict grammar, and give it tests
Merged
#639 fix(617): make the cross-repo skills real symlinks and reconcile the ersatztv skill
Merged
#635 fix(616): paging is 0-based — correct the MCP contract, fix a live 1-based SPA caller, un-cap two MCP tools
Merged
#630 fix(622): bind H10 merge consent to the reviewed sha via a required commit status
Merged
#613 fix(491): unique index on LibraryFolder(LibraryPathId, PathHash) + tolerate concurrent insert
Merged
#626 [THROWAWAY] probe(622) fix
Merged
#625 [THROWAWAY] probe(622) nofix
Merged
#624 [THROWAWAY] probe(622): commit pushed AFTER scheduling
Merged
#623 [THROWAWAY — DO NOT MERGE] probe(622): does a MISSING required status block auto-merge?
Merged
#619 feat(610): split the decision corpus into one YAML-frontmatter file per record
Merged
#618 fix(609): the decisions rationale-edit marker is a git trailer, not a bare substring
Merged
#607 fix(496): per-library server identity for music videos — itemId diff + soft trash
Merged
#612 feat(484): suppress the media-server sweep on projection failures; reject the ratio threshold
Merged
#611 fix(503): map WatermarkLocation.MiddleCenter to a centered overlay position
Merged
#605 feat(603): adopt OKF's optional stale-after and Sources: decision-record metadata
Merged
#591 feat(445,533): headless Playwright UI-E2E flows + fix e2e-local readiness probe
Merged
#601 fix(460): write null LastScan on disable-sync instead of the MinValue sentinel
Merged
#598 chore(586,594,485): PID-scoped E2E cleanup, ci-image-pin length guard, .gitignore core fix
Merged
#602 fix(500): dedup incoming metadata collections so a duplicate name inserts once
Merged
#588 chore(docs): trim derivable content from CLAUDE.md, lazy-load the task-completion protocol
Merged
#593 docs(592): record that a skipped CI context is not red
Merged
#589 feat(440): per-source weight steppers + exclude/add-untagged in the Auto-Tune DetailPanel
Merged
#585 chore(583): make per-agent model routing a hard constraint + PreToolUse gate
Merged
#584 feat(436): arbitrary-depth rule-builder group nesting
Merged
#579 feat(437): inline RuleBuilder smart-query authoring in Channel Builder
Merged
#581 feat(415): per-channel fault detection — server-derived health object + Problems filter
Merged
#577 feat(438,435,434): RuleBuilder validation, relative-date operators, DB-sourced facet typeahead
Merged
#575 feat(414): stamp immutable Channel.Origin (auto-tuned vs user-created) and surface it
Merged
#576 fix(458): reject duplicate names on playlist & playlist-group rename
Merged
#574 harden(421,559): percent-encode access_token in IPTV URLs, redact from logs, no-store on tokened manifests
Merged
#573 feat(392): per-schedule clock-boundary padding toggle + 60-min increment
Merged
#571 fix(570): On Now/Next overlay YAML renders (font_family + format_datetime)
Merged
#569 feat(74): per-channel On Now/Next transient overlay
Merged
#566 refactor(395): dedup Scripted≡YAML enumerator construction into ContentEnumeratorBuilder
Merged
#564 test(381): Sequential (YAML) playout golden; document Scripted deferral
Merged
#562 feat(297): add channelId to PlayoutListItemResponseModel; SPA reset keys directly
Merged
#561 fix(248): focus-trap the shared modal overlay so Tab can't escape a dialog
Merged
#560 fix(552): mint a short-lived JWT so the SPA reaches /iptv/* under JWT auth
Merged
#558 test(512): flush LibrariesScreen scan-poll chain deterministically instead of waitFor timeouts
Merged
#557 fix(553): exclude bot-authored issues from the queue selector
Merged
#551 feat(60): in-browser channel preview on the channels list
Merged
#556 docs(jellyfin-skill): correct stale "music videos are typed Movie" gotcha
Merged
#555 fix(177): map Album/Track in the Jellyfin music video projection
Merged
#550 fix(135): from-lineup advanced overrides can express "clear to none"
Merged
#546 fix(539): WorkAheadSlots.Release never publishes a negative count
Merged
#547 ci(545): require a **Signals:** line on decision records
Merged
#549 docs(skill): correct the ersatztv skill for the fork — it described upstream
Merged
#544 docs(542): record the workflow lore, then prune the kickoff doc to instructions
Merged
#543 chore(541): fast-forward the shared checkout at session end (H13)
Merged
#540 fix(68): rebuild on-demand channel guide (and mirrors) on thaw
Merged
#538 fix(536): enforce workAheadSegmenterLimit with an atomic slot claim
Merged
#537 ci(535): split PR-only git gates into pr-checks.yml so release tags don't red
Merged
#534 docs(524): triage #237's 111 comments — no decision retrofit is owed
Merged
#531 docs(release): v26.12.0 headline — ErsatzTV MCP server (#58) + external-logo download (#525)
Merged
#530 fix(529): floor QSV extra hardware frames so an unthrottled read can't exhaust the pool
Merged
#528 feat(525): external channel-logo URLs download + cache at save time (not fetched at render)
Merged
#527 feat(520,521): full decision-corpus migration + parallel-orientation startup rewrite (PR2 of 2)
Merged
#526 feat(521): decision-lifecycle machinery — keyed records, validator, generated catalog (PR1 of 2)
Merged
#518 fix(511): bound remote graphics-engine image fetches (timeout, size cap, decode cap, redirects, pooling)
Merged
#517 feat(#58): ErsatzTV.Mcp — read + cautious-write MCP server over /api/v1
Merged
#516 fix(350): burst-read the first HLS segments so cold start isn't readrate-bound
Merged
#513 fix(502): render the on-screen bug for external-URL channel logos
Merged
#514 docs(release): Komodo stack is jazz-media; no auto-update fallback
Merged
#509 ci: move both docker build jobs off the small lane
Merged
#507 docs(release): v26.11.0 headline is the QSV VA-API decode fix (#498) + unified logo bug (#67)
Merged
#506 feat(498): QSV profiles can decode via VA-API (Prefer native decoder)
Merged
#504 feat(67): one logo drives both the listing and the on-screen bug
Merged
#501 docs(release): prepare v26.11.0 promotion — correct the deploy host to jazz
Merged
#499 fix(497): reconcile music-video metadata collections on Jellyfin rescan
Merged
#490 docs(489): spec + implementation plan for Jellyfin mixed-content libraries
Merged
#493 feat(489): support Jellyfin mixed-content libraries
Merged
#495 fix(494): reconcile removed music videos in Jellyfin scanner
Merged
#492 fix(488): resolve LibraryFolder from DB so Jellyfin music-video scans stop crashing
Merged
#486 fix(480): probe external-JSON remote-stream URLs before ffmpeg
Merged
#482 feat(472): sub-split the HLS cold-start startup phase
Merged
#483 fix(477): guard media-server library sweeps against successful-but-empty fetches
Merged
#479 fix(473): probe media-server remote streams before handing the URL to ffmpeg
Merged
#481 fix(476): cascade FileNotFound from removed shows/seasons to descendants
Merged
#475 ci(412): sample true peak-anon in the test job, not cache-inflated memory.peak
Merged
#471 perf(469): format gate uses dotnet format whitespace --folder (~480s → ~0.5s)
Merged
#470 test(444): deterministic functional-E2E for the playout-build lock 409 + isLocked projection
Merged
#468 feat(431): TTL-cache health-check results; ?refresh=true forces a fresh run
Merged
#467 fix(464): render real channel logos in guide grid + channels list
Merged
#466 docs(404): mirror the weight UI into the MultiCollections design prototype
Merged
#465 fix(463): bound the schedules "Active schedule" selector so it stops overlapping the header
Merged
#462 feat(404): weighted-distribution SPA — per-source weight inputs + WeightedShuffle order
Merged
#461 feat(queue): deterministic select-queue.sh — stop re-deriving the selector by hand
Merged
#459 fix(409): report never-scanned LastScan as null for API/MCP parity (migration + read coercion)
Merged
#455 feat(420): skip re-validating an already-green identical merge tree
Merged
#457 feat(403): make unsupported PlaybackOrder loud at build time + tripwire
Merged
#456 fix(401): reject Mirror channel with playout (422) + repair dead else-branch
Merged
#454 fix(327): validate playlist name on rename (reject empty/whitespace/too-long)
Merged
#451 fix(409,447): LibrariesScreen 'Never scanned' label + stabilize flaky scan-poll test
Merged
#453 fix(410): log scan cancellation below ERROR (user-initiated, not a failure)
Merged
#452 ci(338): distinguish ZAP warning (exit 2) from failure (exit 1) in security-scan
Merged
#450 fix(367): correct Plex budget-exhausted guidance when no servers exist
Merged
#449 fix(310): strip UTF-8 BOM from the legacy .cs files #269 touched
Merged
#448 feat(396): collapsible sidebar + nav-group accordions
Merged
#446 feat(350): instrument HLS cold-start latency (phase split + feature flags)
Merged
#443 test(363): functional-E2E harness — deterministic scan-lock + collections-lock 409 flows
Merged
#442 feat(293): paginate GET /api/v1/search/all-items to cap DoS exposure
Merged
#441 fix(308): idempotent concurrent Add*ToCollection instead of a composite-PK 500
Merged
#439 feat(425): per-source rotation weights + query corrections for auto-tune channels
Merged
#433 feat(176): visual rule builder for the SmartCollection editor
Merged
#432 feat(386): Auto-Tune per-channel DetailPanel slide-over (SPA)
Merged
#430 feat(164): guided remediation for health checks
Merged
#428 feat(385): per-channel overrides in auto-tune bulk-create
Merged
#424 ci: pre-push guard against pushing an uncommitted working-tree change (H13)
Merged
#426 docs(lore): run local gate + cold review BEFORE pushing to Gitea CI
Merged
#429 fix(416): docs-only skip never fired — detect against FETCH_HEAD (shallow-checkout safe)
Merged
#423 fix(320): break troubleshoot segment-wait loop on ffmpeg failure
Merged
#422 ci(416): skip heavy jobs on docs-only changes without bricking the merge gate
Merged
#419 fix(376): XML-escape access_token value in XMLTV guide output
Merged
#402 feat(70): weighted / fair-share content distribution (WeightedShuffle playback order)
Merged
#417 docs(lore): batching, no "main checkout", trust the queue, diagnosing CI reds
Merged
#405 fix(72): report a real per-channel playout count and flag channels that will never play
Merged
#413 chore: PreToolUse guard that blocks a commit/push with a BOM'd touched .cs
Merged
#411 ci(406): disable persistent compiler servers, cap the services: mysql, report peak RSS
Merged
#407 ci: move api-docs and format back to ubuntu-latest (refs #406)
Merged
#408 fix(264): record library-level LastScan after a successful local scan
Merged
#397 feat(384): auto-tune DetailPanel content-source member read endpoint
Merged
#399 ci(390): shared CI toolchain image + drop 110s apt-ffmpeg + rebalance runner lanes
Merged
#391 feat(380): extract shuffle-source construction to ShuffleSourceBuilder (kill PlaylistEnumerator's cross-engine reach-in)
Merged
#394 design(388): mirror full ChicoryTV design system to prod + design-sync reminder hook
Merged
#393 test(77): characterize clock-boundary schedule padding + docs
Merged
#389 feat(69): Auto-Tune SPA wizard (Configure → Preview → Create) — PR2
Merged
#387 feat(71): per-playout reshuffle + shuffle-state surfacing
Merged
#382 test(163): golden characterization tests for playout building (Classic + Block)
Merged
#379 feat(69): auto-tuning backend — enumerate library metadata, preview + bulk-create channels (PR1)
Merged
#375 feat(analyzers): enable incremental latest-All enforcement
Merged
#378 fix(spa): body margin + nav box-sizing resets (#373, #377)
Merged
#374 feat(iptv): add configurable advertised base URL for M3U/XMLTV (#340)
Merged
#329 chore(deps): update dependency jetbrains.resharper.globaltools to 2025.3.4.1
Merged
#328 chore(deps): update dependency humanizer.core to 3.0.10
Merged
#370 ci(coverage): collect code coverage and publish a summary (refs #15)
Merged
#372 docs(queue): exclude parked selector candidates
Merged
#371 fix(api): protect local library path details
Merged
#369 docs(queue): cascade selector through priority tiers
Merged
#368 fix(api): report direct streams as on air
Merged
#366 fix(web): coherent, recoverable Plex authorized-but-no-servers state (#345)
Merged
#365 docs: make queue selection non-terminal
Merged
#362 ci: advisory functional-E2E curl harness (#299)
Merged
#361 refactor(web): extract ChicoryTV shell and routing
Merged
#359 refactor(web): extract Guide screen
Merged
#360 refactor(web): extract Dashboard screen
Merged
#356 docs(queue): record cheap-worker launch config
Merged
#352 docs(queue): start tool-bearing selectors at low effort
Merged
#351 refactor(spa): extract Playouts screen
Merged
#348 docs(queue): enforce milestone-aware picker ranking
Merged
#349 fix(spa): clear dirty guard before saved navigation
Merged
#346 docs(e2e): record real media-source validation results
Merged
#343 docs(workflow): enforce session-wide cost routing
Merged
#341 Add Cross-Origin-Resource-Policy baseline header
Merged
#337 docs(release): prepare v26.8.0 promotion
Merged
#331 feat(ci): #314 — authenticated black-box security scan + Microsoft.OpenApi HIGH-vuln pin
Merged
#325 fix(#172): API hardening — null-name 500s, duplicate template items, unreachable 404
Merged
#326 feat(api): #286 — mount the whole /api surface at /api/v1
Merged
#324 fix(#238): wire TopBar primary-action on create screens, drop dead buttons
Merged
#322 fix(api): #265 — If-Match evaluates per RFC 7232 (valid-but-non-matching -> 412)
Merged
#323 security(#319): enforcing CSP + Permissions-Policy on the host
Merged
#316 #295 PR2: SPA session cutover + #301 side-effecting-GET POST-ification
Merged
#321 feat(ci): #315 migration-on-prod-copy smoke for the release path
Merged
#318 fix(process): #317 merge-consent gate auto-grants on satisfied path (no double-prompt)
Merged
#313 process: #311 H11 rebase-hook + PR-scoped format CI + #312 H12 qualification audit
Merged
#309 docs(process): #303 follow-ups — Codex-skip rubric + write-path live-E2E requirement
Merged
#307 fix(api): #269 rotate aggregate ETag on Collection/Playout config siblings
Merged
#306 chore(process): #303 H10 — review-verdict merge-gate (latest commit must be reviewed)
Merged
#305 chore(process): #303 Wave 3 — H3 root-screenshot guard + H9 decisions.md append-only guard
Merged
#304 ci: #303 H4/H5 blocking api-docs gate — fail on stale OpenAPI artifacts
Merged
#302 fix(api): #269 force-write non-If-Match root writers past a concurrent Version bump
Merged
#300 feat(api): #295 PR1 — browser SPA session auth (session-OR-key gate, server-only)
Merged
#298 feat(api): #271 collections scan-status REST surface + authoritative SPA reconcile
Merged
#296 #197 Bundle C: OpenAPI contract honesty (#287) + wrap raw VMs / nullable DTOs (#288) + channel re-key
Merged
#291 security(#283): sniff artwork content type from bytes, remove serve-side ?contentType= reflection
Merged
#294 ci: make the MySql migration-apply resilient to concurrent-runner contention
Merged
#292 security(#197): fail-closed API auth posture (Bundle A: #280/#281/#282/#284/#285)
Merged
#290 docs(#197): record Phase-0 hardening decisions in decisions.md
Merged
#279 security(#197): safe hardening — constant-time key compare, clamp playout paging, security headers
Merged
#277 ci: prod follows :prod — remove version-pin bump job (#275 rework)
Merged
#276 #259: content-aware stable child identity for schedule-item replace
Merged
#275 ci: restore bump-prod-compose auto-deploy on v* release
Merged
#274 #91b — remove legacy Blazor Server UI
Merged
#273 chore(dev): husky pre-commit / pre-push / commit-msg guardrails
Merged
#270 feat(#253 PR3): optimistic-concurrency fan-out — Diff + Scalar aggregates
Merged
#268 #253 PR2 — optimistic-concurrency fan-out (Template, DecoTemplate, Playlist, schedule-items)
Merged
#272 #91b: wire deep-scan + external-collections buttons into LibrariesScreen
Merged
#267 feat(235): async-op API contract normalization + playout build observability + F9 scan endpoints
Merged
#266 fix(app): post-commit side effects on CancellationToken.None + guide-xml/empty-list hardening (#254)
Merged
#263 feat(api): optimistic-concurrency contract for replace-all PUTs — PR1 infra + Block reference (#253)
Merged
#262 feat(media-sources): SPA management screens + write REST API (#202)
Merged
#261 docs(91b): auth-posture sign-off + rollback-tag procedure for Blazor removal (#205, #206)
Merged
#260 fix(ui): pattern-based legacy→SPA redirect matcher for parameterized routes (#204)
Merged
#258 fix(scheduling): stop silently resetting fill-group state + invalidate deco edits (#251, #252)
Merged
#250 fix(locking): release troubleshooting + playout locks on all terminal paths (#233, #234)
Merged
#249 refactor(spa): extract ChannelsScreen from App.tsx (#244, epic #243 phase 1)
Merged
#242 fix: reviewer post-merge blockers — empty-lineup bare create (#212) + dirty-guard popstate/shuffle-toggle (#230)
Merged
#241 fix(locking): EntityLocker atomicity + scan-lifecycle honesty (#231, #232)
Merged
#229 feat: schedules editor full mutation depth + channel-editor gaps (#207, #212, #126)
Merged
#240 test(api): locked-path 409 guard tests for ReplaceAlternateSchedules + ReplaceTemplates (#215)
Merged
#239 Integration: review-gates batch — #220/#215/#217/#219/#218 + #213 remainder (PRs #223–#228)
Merged
#222 fix(spa): gate mutation controls on stale result sets during refetch (#221)
Merged
#216 feat: shared Add-to layer — search + media mutation surface (#208, #209)
Merged
#214 feat: playouts delete/reset/erase + collections custom-order/all-kind adds + parity nits (#210, #211, #213)
Merged
#201 fix(openapi): spec property naming now mirrors the runtime Newtonsoft serializer (#198)
Merged
#200 fix(api): existence-check rerun-collection selectedId per selection type (#193)
Merged
#199 feat: SPA playback troubleshooting screen + status/subtitles/stream-selectors endpoints (#145)
Merged
#196 docs+ci: harden docs-first rule + non-blocking parity-doc reminder
Merged
#195 feat: playlist CRUD API + SPA editor (#153)
Merged
#194 feat(spa): multi-collection & rerun-collection editor screens (#151, #152)
Merged
#192 ci: speed up build pipeline (NuGet cache, shallow checkout, jar layer reorder) (#190)
Merged
#188 feat(api): REST CRUD for multi-collections and rerun-collections (#151, #152)
Merged
#189 feat(api): GET /api/collections/{id}/items (paged) — full collection contents (#155)
Merged
#187 feat: quick wins — security-registry scan, Trakt SPA link, parallel search, dead "New Group" sweep
Merged
#186 docs: testing map + generated endpoint index (#185)
Merged
#183 feat(web+api): media detail endpoints+pages, image folder browser (#141, #161 items 3+5)
Merged
#182 feat(web+api): block-playout history + sequential-YAML validator (#145, #158 items 4–5)
Merged
#181 fix(web+api): library picker artwork URLs + season drill-in instead of tile flooding (#180)
Merged
#179 feat(web+api): playout alternate schedules + templates editors, default-deco read-side (#144 S6, #162)
Merged
#175 feat(web+api): deco templates (#144 S4, #162)
Merged
#174 feat(web+api): decos + deco groups, playout default deco, playlist/search pickers (#144 S3, #162)
Merged
#173 feat(web+api): scheduling templates + block/template copy (#144 S2, #162)
Merged
#171 feat(web+api): blocks CRUD, items editor & preview (#144 S1, #162)
Merged
#170 feat(web+api): playout create for all kinds + detail updates (#144 S5, #162)
Merged
#168 feat(web+api): media browse, search & trash for SPA parity (#141)
Merged
#169 test(web): make Libraries scan-polling tests deterministic (fixes #157)
Merged
#167 feat(web+api): Trakt lists screen + REST API for SPA parity (#142)
Merged
#166 feat(web+api): FFmpeg profile, filler preset & watermark editors for SPA parity (#143)
Merged
#165 feat(web+api): logs & troubleshooting screens for SPA parity (#145)
Merged
#156 feat(web): collections management screen — manual + smart collections (#140)
Merged
#154 feat(web): dedicated channel edit screen (#146)
Merged
#150 feat(web): Classic UI link in Settings + ChicoryTV cue on redirecting Blazor nav links (#147)
Merged
#132 chore(deps): update dependency entityframeworkprofiler.appender to 6.0.6053
Merged
#61 chore(deps): apply open Renovate patch updates
Merged
#148 feat(web): SPA cutover — root route (#91)
Merged
#139 feat(web): ChicoryTV rebrand (#90)
Merged
#138 feat(web): Settings screen (#93)
Merged
#137 fix(deps): bump Scriban.Signed 6.5.2 → 7.2.5 (GHSA-5wr9-m6jw-xx44)
Merged
#136 feat(web): Channel Builder (#89)
Merged
#134 feat(api): composite create-channel endpoint (#63)
Merged
#133 feat(api): channel templates entity + CRUD (#64)
Merged
#130 feat(api): library browse + search endpoints (#65)
Merged
#129 feat(web): Guide / EPG screen (#85)
Merged
#128 feat(web): Libraries screen (#88)
Merged
#127 feat(web): Playouts screen (#87)
Merged
#125 feat(web): Schedule editor screen (#86)
Merged
#124 feat(web): Channels screen (#84)
Merged
#123 feat(web): Dashboard real data sources (#109)
Merged
#121 feat(core): track active sessions for direct streaming modes (#99)
Merged
#122 fix(docker): use valid node:22-bookworm-slim base for web-build stage
Merged
#120 feat(web): ChicoryTV SPA foundation (#59 stack)
Merged
#112 feat(api): channel on-air / now-playing state endpoint (#97)
Merged
#119 feat(api): JSON channel guide endpoint (#102)
Merged
#118 feat(api): schedule item duration estimates (#111)
Merged
#117 feat(api): artwork upload endpoint (#104)
Merged
#115 feat(api): media sources + scan status endpoints (#103 #106)
Merged
#116 feat(api): playout read endpoints (#100 #101 #107 #110)
Merged
#114 feat(api): health endpoints (#108)
Merged
#113 feat(api): filler/watermark/graphics list endpoints (#105)
Merged
#56 fix(ffmpeg): align transcode pipelines with ffmpeg 8
Merged
#55 feat(jellyfin): sync MusicVideo libraries
Merged
#54 feat(api): default-deny mutating API writes
Merged
#53 test: make channel logo generator testable
Merged
#52 feat(api): standardize FFmpeg profile endpoints
Merged
#51 feat(api): add playout REST endpoints
Merged
#50 feat(api): add schedule REST endpoints
Merged
#47 fix(api): standardize error response contract
Merged
#45 feat(api): add collections REST endpoints
Merged
#44 feat(api): REST API foundation + Channels CRUD (#2a)
Merged
#41 fix: make filler scheduling tests timezone-independent (fixes #24)
Merged
#40 test: golden tests for XMLTV guide output (#28)
Merged
#33 ci: gate image build on migrations + #1 handoff
Merged
#32 docs: retroactive contributors/style guide (#10)
Merged
#31 ci: assert key IPTV endpoints in the container smoke test (#16)
Merged
#30 ci: EF migration integrity checks for SQLite + MySql (#13)
Merged
#29 test: golden-file tests for M3U output (#11)
Merged
#27 test: enforce layer dependency direction with NetArchTest (#12)
Merged
#26 build: static-analysis pack foundation at suggestion (#15, increment 1)
Merged
#23 ci(renovate): enable Dockerfile manager for the HTTP Gitea registry
Merged
#20 fix(deps): clear NCalcSync + SQLitePCLRaw vulnerability advisories (#8)
Merged
#19 ci(renovate): fix GitHub PAT secret name + bump image pin
Merged
#18 ci: self-hosted Renovate (NuGet CPM + Gitea Actions)
Merged
#17 build: Central Package Management + scheduled vulnerability scan (#14)
6 Pull requests proposed by 2 users
Proposed
#761 chore(deps): update dependency meziantou.analyzer to 3.0.195
Proposed
#804 chore(deps): update dependency sqlitepclraw.bundle_e_sqlite3 to 3.0.5
Proposed
#805 chore(deps): update dependency system.commandline to 2.0.11
Proposed
#828 chore(deps): update dependency cliwrap to 3.10.5
Proposed
#829 chore(deps): update lucene.net to 4.8.0-beta00018
Proposed
#878 fix(830): a write failure reports to a surface that outlives the dialog that started it
416 Issues closed from 1 user
Closed
#876 docs.no-session-narrative reaches hooks and code comments, but nothing has ever swept them — 4 known sites
Closed
#893 page_statuses still terminates on its first empty page — is /statuses/{sha} subject to #870's post-pagination filtering?
Closed
#869 Finish the 1.25.4-dated CI claim sweep #747 deliberately did not complete
Closed
#891 ETV_HOOK_FIRE_LIB is SOURCED from an env-var path in 12 hooks — a decoy tree's code runs inside the gate
Closed
#855 Nothing couples ci-image.yml's push.paths to ci-image-pin's expected pathspec
Closed
#887 Every image build fails: completeAnnotations.guard.test.ts needs the git index, and the Dockerfile's exclude list is hand-maintained
Closed
#900 chore(release): cut and promote v26.15.0 on 736649b3b (main head could not build an image)
Closed
#858 pretooluse-merge-consent.sh resolves its verdict classifier from $CLAUDE_PROJECT_DIR — an env var as a security input
Closed
#859 Merge-gate branch-protection read: a malformed rule states a cause that did not happen, and the endpoint is now fetched twice
Closed
#870 The timeline walk's null terminator is defeatable: Gitea pages BEFORE it filters, so a page of inline-code comments reads as exhaustion
Closed
#880 Schedule-item recurrence fields: an omitted array means "never applies" on write but "unrestricted" on read
Closed
#849 review-verdict.yml post-write verification: three routes that leave an exemption success over a human failure
Closed
#845 post-review-verdict.sh does not check that its own account is on the gate's H10_REVIEWERS allow-list
Closed
#886 release.verdict-vocabulary-shared explains the sentinel with a set -u mechanism that measurement refutes
Closed
#853 workflow_dispatch still loads attacker YAML from an arbitrary ref — four workflows, no ref restriction
Closed
#836 :latest images ship InformationalVersion 0.0.0 — a --depth=2 fetch grafts the build job's full clone shallow
Closed
#820 Complete<T> proves its semantics but not its APPLICATION — nothing derives the set of SPA full-replace construction sites
Closed
#812 Remediate the 21 session-narrative sites #784's sweep found — 21 judgements, not a regex
Closed
#823 Scheduling collection-valued columns: is a runtime null reachable on DaysOfMonth / MonthsOfYear / DaysOfWeek?
Closed
#824 ElasticSearchIndex.UpdateSong has no regression test — an Elastic-only reintroduction of the #701 mutation stays CI-green
Closed
#819 The SPA page-size guard enumerates web/src with a Vite glob while claiming completeness
Closed
#809 The production-hook-fire-log isolation guard is per-test, but its claim is per-suite
Closed
#822 test_the_suite_does_not_write_to_the_PRODUCTION_log uses global mutable state as its oracle — any concurrent session reddens it
Closed
#664 pr-changed-files.sh head binding cannot see an A→B→A force-push across its paging round-trips
Closed
#803 Head-ABA: a force-push H1->H2->H1 during paging defeats pr-changed-files.sh, and three contracts still deny it
Closed
#789 Derive the CI toolchain population from workflow-owned metadata, not TOOLCHAIN_JOBS
Closed
#786 Extend the machine-checked guard inventory to inline workflow-job guards
Closed
#796 A verification harness is itself unproven code — five false greens, each created by the fix for the last
Closed
#763 Page both /statuses/{sha} reads in review-verdict.yml — limit clamps to 50, so the post-write race check can miss a raced verdict
Closed
#747 Re-verify the Gitea 1.25.4-pinned CI claims after the 1.27.1 upgrade
Closed
#781 Plugin/MCP config hygiene: retire what is enabled and never invoked, de-duplicate the gitea server
Closed
#799 serena is enabled and starts fine, but its tools never reach a session — establish why, then use or disable it
Closed
#787 The dropped-step guard's SCOPE is a dated comment, not a check, against branch protection
Closed
#748 Declare permissions: on the status-writing workflows so the Gitea Restricted token default can be enabled
Closed
#744 ci-image.yml's push trigger has no branches: filter — any branch push runs attacker YAML on a docker-capable runner
Closed
#835 Guard the persist-credentials convention — after #744, with no exemption list
Closed
#742 Tighten review-verdict.yml provenance from "non-null creator" to an allow-list of approved reviewers
Closed
#735 Validate FFmpeg profile numeric fields to sane ranges instead of silently transforming them, and expose readrate pacing as a bounded field
Closed
#788 One shared verdict vocabulary instead of two shell copies plus a parity test
Closed
#732 On Now / Next overlay: give it a boxed background for legibility, and enable it on all channels by default
Closed
#746 docker-build.yml checkouts should set persist-credentials: false — after the || true fetch masking is removed
Closed
#734 SPA: field-level progressive disclosure — short summary → hover popup → (future) deep-dive docs link
Closed
#755 Project boundary: ersatztv owns the fork code, media-management owns channel operations
Closed
#708 Reproduce #698 route 2 live: push code onto a renovate-authored PR branch and confirm the manifest allow-list refuses the exemption
Closed
#690 Rerun collections: paged list TotalCount ignores the search query, so the SPA renders empty pages
Closed
#758 GetPagedPlayouts: TotalCount ignores the query filter, so a filtered page reports the unfiltered total
Closed
#721 Auto-Tune proposal rows should be a grid — channel numbers do not line up, and the name renders twice
Closed
#740 AddItemsDialog.runSearch has no stale-response or is-mounted guard (pre-existing, surfaced during #685)
Closed
#807 The SPA's hand-built request objects can silently drop an OPTIONAL DTO field
Closed
#701 Search indexers mutate SongMetadata.Artists on a possibly-tracked entity (??= []) — same shape rejected in #691
Closed
#792 post-review-verdict.sh exits 0 when it deliberately writes NO status
Closed
#772 The pinned CI toolchain image can vanish from the registry and take ALL container CI down, with no signal but a pull error
Closed
#806 Guard populations over FILES should derive from the git index, not a filesystem walk
Closed
#790 An executable clause-level mutation harness for the shell and python guards
Closed
#780 Reconcile Python tooling: commit a ruff config and enforce it, or stop claiming we enforce it
Closed
#784 Generalize the no-session-narrative rule from the kickoff file to all docs — the reader never saw the earlier draft
Closed
#785 Mutation proofs for the 19 unproven guards, worst-consequence first
Closed
#779 Test the deny path with the production config value, and assert full-replace field lists
Closed
#778 Audit read-then-write against live remote state: pin a version or use compare-and-set
Closed
#794 A fix ships a test witnessed failing BEFORE the fix — mechanise it by reverting the code side and asserting red
Closed
#776 Make hooks report that they fired — PreToolUse/PostToolUse execution is currently unobservable
Closed
#797 pretooluse-bom-guard.sh is fail-open wherever xxd is not installed — including the CI runner
Closed
#777 csharp-lsp and typescript-lsp are broken; the "workflow agents must use csharp-lsp" guidance is stale
Closed
#774 Guard convention: derive the expected set from the authoritative source and assert equality — never filter, never sample
Closed
#775 Every guard ships with a proof it can go red: delete that guard alone, the suite must fail
Closed
#773 Root-cause the recurring defect shapes across closed issues, then build hooks/tooling that make them hard to repeat — plus an audit of the tooling we already have and don't use
Closed
#767 Make the delimiter ban fail-CLOSED on the release path — build's Smoke step is still droppable on a v* tag push
Closed
#720 docs(ci-cd): a Komodo stack named ersatztv now exists on jazz — and it is NOT prod
Closed
#756 Extend the dropped-step guard to docker-build.yml's required jobs, where a dropped step is fail-OPEN
Closed
#751 review-verdict.yml's classify/post step never executes — job goes green, review-verdict/h10 is never posted automatically
Closed
#754 MCP ersatztv_update_channel omits graphicsElementIds — cannot set the On Now/Next overlay, and silently strips it
Closed
#757 MCP tool catalog: query parameters are unguarded — list_playouts omits query, get_playout_items omits showFiller
Closed
#719 H11 pre-push guard blocks a tag-only push, on every release cut
Closed
#743 review-verdict/h10 is bypassable without forging it: direct pushes to main are server-side permitted
Closed
#697 ETV_STATUS_AUTH can write commit statuses, so any head-resolved workflow can still forge review-verdict/h10
Closed
#685 CollectionsScreen AddItemsDialog windows the whole media-library type on an empty query, with no truncation surfaced (§3b deviation)
Closed
#674 decisions_validate.py stays green on frontmatter PyYAML rejects — an apostrophe in a single-quoted scalar (hit twice in one session)
Closed
#688 decisions_validate ceiling calibration test is one line from red — any record ≥61 prose lines fails script-tests
Closed
#726 Embedded BITMAP subtitle (PGS/DVD) burn-in + -readrate halves transcode to 0.53x realtime — Live TV buffering
Closed
#707 pr-changed-files.sh paging can drop a path when the base branch advances mid-enumeration
Closed
#711 .codex/ mirrors the gate-enforcing hooks but is absent from the merge gate's PROTECTED list
Closed
#706 review-verdict/h10 writes are not serialized — a stale run can overwrite a fresher verdict (ABA retarget + human-rejection race)
Closed
#715 chore(deps): land the three stalled Renovate patch bumps as one batch (#679, #680, #681)
Closed
#713 chore: ignore .codex/ and stop shipping a plaintext Gitea credential in tracked docs
Closed
#698 The review-verdict/h10 exemption path decides from mutable PR state — three routes to a forged exemption
Closed
#672 review-verdict.yml is head-resolved, so a PR editing it can self-approve the required check
Closed
#691 SongVideoGenerator dereferences the nullable SongMetadata.Artists unguarded — NRE on the playback path
Closed
#671 Rerun collections: the list endpoint returns a null selection for every row, and the detail GET 500s or nulls for five media types
Closed
#668 Facet-value typeahead misses accented values on the EF-sourced fields (LOWER() is ASCII-only on SQLite)
Closed
#684 main is red: the #650 pageSize call-site guard keys its registry on line:column, so any merge that shifts a line breaks it
Closed
#578 #434 follow-ups: typeahead combobox polish + source limitations
Closed
#650 Two more list loads truncate at the cap — but at-cap, so #644's over-cap grep could not see them
Closed
#651 Library-browse pickers need a searchable source, not a 100-row window or a full-library crawl
Closed
#649 The ENFORCED review-verdict.yml guard is weaker than the advisory local hook — duplicated security logic has drifted
Closed
#632 A PR base change leaves the head sha — and so the review-verdict/h10 status — unchanged
Closed
#662 Typeahead artist suggestions miss free-text credits; album_artist 404s — value-converted list columns have no suggestion source
Closed
#648 Pin or preflight jq in CI: the runner ships 1.6, dev machines ship 1.8.x, and that gap silently broke three shell gates
Closed
#510 WatermarkSelector: the deco path has a different missing-logo policy than the three precedence levels
Closed
#644 Seven more SPA list loads silently truncate at the server cap (same class as #634, one screen over)
Closed
#505 QSV native-decode path tonemaps HDR in software (route through tonemap_qsv)
Closed
#620 decisions corpus consolidation has no owner — and after #610 the budget number stops reporting it
Closed
#647 H10 verdict classifier is inert on jq 1.6: contains("�") matches every string, and a parse error is indistinguishable from an empty list
Closed
#643 Merge-consent gate fails OPEN on jq 1.6: a transport failure mid-pagination lets the docs-only exemption fire over a PARTIAL file list
Closed
#631 scripts/tests/ is never executed by CI — the Python test suite is local-only
Closed
#621 decisions: a record file that fails to parse is silently invisible — no structural "one keyed record per file" check
Closed
#633 OpenAPI pageNum parameters carry no description, so the 0-based contract is invisible to REST consumers
Closed
#634 Rerun-collection picker in SchedulesScreen silently truncates at 100 (asks for pageSize 1000, server clamps to 100)
Closed
#629 merge gate: false-opens in the H10 verdict classifier — an undefined token, code blocks (fenced/indented/HTML), a URL-borne sha, and a read path that failed open
Closed
#617 .claude/skills/jellyfin/ is a stale divergent copy, not the symlink CLAUDE.md describes — it documents auth that v12 only accepts by legacy opt-in
Closed
#615 Jellyfin merges <Base> - <variant>.mp4 music videos into one multi-version item — Behind the Music (61 files) and Top of the Pops (24 files) each land as a single ErsatzTV item
Closed
#616 MCP/API paging traps: pageNum documented 1-based but is 0-based, pageSize cap doesn't clamp the offset, and playout rows carry no channelId
Closed
#622 merge gate: docs-only exemption is computed from a TRUNCATED file list (confirmed); auto-merge scheduling also freezes H10 consent (structural)
Closed
#491 LibraryFolder has no unique index on (LibraryPathId, Path) — concurrent GetOrAddFolder can insert duplicates
Closed
#610 decisions: split the monolithic corpus into one YAML-frontmatter file per record
Closed
#609 decisions-validate: [decisions-edit] is a bare substring match — a commit that merely *describes* the token disarms the guard
Closed
#496 Music videos have no per-library identity — global GetOrAdd path dedup can cross-library false-trash
Closed
#487 MCP acceptance case: populate the empty music collections via the MCP write path (not by hand)
Closed
#484 Media-server scanner: ratio-threshold + projection-failure detection for the empty-fetch guard
Closed
#503 Watermark MiddleCenter renders bottom-right — missing switch arm in OverlayWatermarkFilter
Closed
#603 decisions: adopt OKF's stale-after and Sources: as optional record metadata
Closed
#445 functional-E2E: add the UI-interactive Playwright (headless) flows (deferred from #363)
Closed
#533 scripts/e2e-local.sh readiness probe hangs on a reused config dir
Closed
#460 MediaSourceRepository writes MinValue LastScan on disable-sync — normalize to null (#409 follow-up)
Closed
#485 Build hygiene: .gitignore core entry silently ignores new files under any Core/ directory (case-insensitive on macOS)
Closed
#586 E2E briefs: scope process cleanup by PID, never a pattern-wide pkill
Closed
#594 ci-image-pin accepts any hex length, not the exact 7-char tag ci-image.yml publishes
Closed
#500 MediaServer metadata reconcile double-inserts on duplicate collection names (Plex movie + Jellyfin music-video update paths)
Closed
#587 chore(docs): trim derivable content from CLAUDE.md and lazy-load the task-completion protocol
Closed
#592 CI monitors: record that skipped is not red (build skips on every PR)
Closed
#440 Auto-Tune DetailPanel SPA: wire per-source weight steppers + exclude/add-untagged to the #425 backend
Closed
#583 Kickoff: make per-agent model routing a hard constraint + a PreToolUse gate
Closed
#436 Rule builder: support nesting deeper than one level (#176 follow-up)
Closed
#437 Adopt RuleBuilder inline in ChannelBuilder & Auto-Tune (#176 follow-up)
Closed
#415 Per-channel fault detection beyond "no playout" (empty schedule, broken source)
Closed
#434 Rule builder: facet-value typeahead for text fields (#176 follow-up)
Closed
#435 Rule builder: relative-date operators ("in the last N days") (#176 follow-up)
Closed
#438 Rule builder: input validation & polish (bundles #176 review minors)
Closed
#414 Channels list: distinguish auto-tuned from user-created channels (origin marker)
Closed
#458 Playlist/group rename should reject duplicate names (like create does) — #327 follow-up
Closed
#178 Idea (far future): Jellyfin plugin to control ErsatzTV from within Jellyfin
Closed
#75 [Blue sky] Themed "Resource Packs" for bumpers / branding / interstitials
Closed
#559 Harden the /iptv ?access_token= transport: redact from request logs + no-store on tokened manifests
Closed
#421 M3U: access_token value not quote-safe in url-tvg="..." attribute
Closed
#392 Clock-align convenience: one-click per-channel/schedule pad-to-boundary toggle + 60-min increment (SPA)
Closed
#570 On Now/Next overlay YAML fails to render (format_datetime arity + null font_family) — #74 hotfix
Closed
#567 Harden channel graphicsElementIds: validate unknown ids (422 not 500) + builtIn discriminator (#74 follow-up)
Closed
#74 [Blue sky] On-screen "On Now / On Next" overlay (channel-surf bug)
Closed
#395 Refactor: dedup Scripted≡YAML enumerator construction (deferred from #380, gated on #381 goldens)
Closed
#523 QSV native-decode (#498) hwupload fails to allocate a QSV surface for certain content — "Cannot allocate memory" kills the stream
Closed
#381 Golden characterization tests for remaining scheduler kinds (Sequential YAML + Scripted)
Closed
#297 Add channelId to PlayoutListItemResponseModel so the SPA reset button keys directly
Closed
#248 SPA dialogs (overlay.tsx) are not focus-trapped / background-inerted
Closed
#552 Mint a short-lived JWT for the SPA so /iptv/* works under JWT-enabled deployments
Closed
#512 Make LibrariesScreen scan-complete test deterministic (stop racing real microtasks under waitFor)
Closed
#553 select-queue.sh ranks Renovate's bot-authored Dependency Dashboard (#22) as a workable pickup
Closed
#60 Backlog: browser channel playback after UI redesign
Closed
#177 Jellyfin music video sync: map Album/Track metadata (credits-overlay completeness)
Closed
#62 Epic: Create Channel — backend prerequisites for the redesigned creation flow
Closed
#135 from-lineup advanced overrides cannot express "clear to none" (null = inherit template)
Closed
#539 WorkAheadSlots.Release hardening: never go negative, and surface UnbalancedReleases somewhere a human will see it
Closed
#545 decisions-guard: require a **Signals:** line (MemPalace recall metadata contract)
Closed
#548 docs: the ersatztv skill described archived upstream, not this fork
Closed
#542 The kickoff handoff doc should be instructions, not incident history — prune the narrative into decisions.md
Closed
#541 H13: session-end must leave the shared checkout fresh — a stale tree serves stale FILES, which no HEAD-reading rule catches
Closed
#68 Resume/bookmark playback position for sequential channels (personal continue-watching)
Closed
#536 workAheadSegmenterLimit is not enforced: the slot check and its increment straddle an await (N concurrent tune-ins all run unthrottled)
Closed
#535 Release-tag builds: small-lane PR-only gate jobs run + fail on v* tag pushes
Closed
#532 Re-measure HLS cold start on prod after v26.12.0+ ships the #529 floor, against #350's 13-sample baseline
Closed
#524 Retrofit #237's durable-only facts into #521 decision records (post-arc follow-up)
Closed
#519 Verify the #350 cold-start burst end-to-end on test, then re-measure on prod
Closed
#529 QSV extra_hw_frames=0 kills transcodes on any unthrottled read — live in prod, and made near-deterministic by #516's burst
Closed
#525 External channel-logo URLs: download + cache at save time instead of fetching at render time
Closed
#521 Make decision knowledge lifecycle-addressable and retrieval-efficient
Closed
#520 Retire #237 from startup; run orientation and mechanical top-five selection in parallel
Closed
#511 Harden remote-image fetching in the graphics engine (timeout, size cap, redirects, pooling, caching, SSRF)
Closed
#58 Backlog: MCP server for ErsatzTV/ChicoryTV API
Closed
#350 Channel cold-start ~7s to first segment — slow tune-in via Dispatcharr/Kodi (heavy transcode profile)
Closed
#502 External-URL channel logos never render an on-screen bug (File.Exists against a URL in WatermarkSelector)
Closed
#515 release: cut and promote v26.11.0 to prod (first release on jazz)
Closed
#474 Music channels dead: Music Videos library has no LibraryPath, so /data/music (30 folders) is never scanned — 8+ collections empty
Closed
#508 Move the two docker build jobs off the small runner lane
Closed
#498 FFmpeg profile should allow separate decode and encode hardware acceleration (QSV encode + VAAPI decode)
Closed
#67 Unified logo/bug image handling (one image drives both, separable)
Closed
#25 Burn down SonarAnalyzer findings in Blazor .razor (analyzer adoption #15)
Closed
#497 JellyfinMusicVideoLibraryScanner.UpdateMetadata drops Tags/Genres/Studios on existing items — Jellyfin metadata edits never sync
Closed
#489 Support Jellyfin mixed-content libraries (currently dropped silently) — keep music/standup segregated from Movies & TV Shows
Closed
#494 JellyfinMusicVideoLibraryScanner does no reconciliation — music videos removed from Jellyfin are never removed from ErsatzTV
Closed
#488 JellyfinMusicVideoLibraryScanner crashes immediately: ArgumentNullException from null LibraryPath.LibraryFolders (feature has never worked)
Closed
#480 External-JSON playout channels still hand ffmpeg an unprobed remote-stream URL (#473 class survives there)
Closed
#472 Split HLS cold-start startup phase into spawn / input-open+probe / first-GOP
Closed
#477 Scanner has no anti-nuke guard: a successful-but-empty media-server fetch flags an entire library FileNotFound
Closed
#478 Channels 102/107 repeatedly fail to tune: h264_vaapi hwupload -22 / exit 234 on prod
Closed
#473 Tune-in hard-fails (ffmpeg exit 8) when a playout item's media file no longer exists — 717 stale episodes across 10 removed shows on prod
Closed
#476 Scanner: FileNotFound does not cascade show → seasons → episodes, so playouts keep scheduling episodes of shows deleted upstream
Closed
#412 CI: peak-memory instrument reports cache-inflated memory.peak; sample true peak anon instead
Closed
#469 CI: speed up the Formatting job (dotnet format --include still loads the whole solution)
Closed
#444 functional-E2E: add the playout-build lock 409 + isLocked projection flow (deferred from #363)
Closed
#431 Backend: TTL-cache PerformHealthChecks (GET /api/v1/health re-runs 14 checks, 4 shell out to ffmpeg, per request)
Closed
#464 Guide + channels list show generated fallback icons instead of the actual channel logo
Closed
#463 Schedules screen: "Active schedule" selector stretches full-width and overlaps the header
Closed
#404 SPA: per-source weight inputs + fair-share toggle in the schedule editor (#70 UI)
Closed
#409 Never-scanned local libraries render "Last scan 12:00 AM" instead of "Never scanned" (LastScan seeded as DateTime.MinValue, not NULL)
Closed
#420 CI: PR run and merge-to-main run re-execute the full matrix over identical code
Closed
#403 Scheduling: an unhandled PlaybackOrder fails silently at five of six dispatch sites
Closed
#398 CI: build once, reuse artifacts across test / migrations / functional-e2e (742s of redundant compilation per run)
Closed
#401 UpdateChannel silently coerces Mirror→Generated when the channel has a playout (should be 422)
Closed
#327 Playlist rename (ReplacePlaylistItems) does no name validation — empty / >50-char names accepted
Closed
#447 Flaky SPA test: LibrariesScreen "stops scan polling and refreshes sources once when scans complete"
Closed
#410 Scan cancellation is logged at ERROR ("Scan was canceled") across all four scan handlers
Closed
#338 ci: distinguish ZAP warning exit 2 from FAIL in security-scan
Closed
#367 Plex: budget-exhausted message says "Use Refresh" but there is no global Refresh when zero servers exist
Closed
#310 De-BOM the 17 legacy .cs files #269 touched (charset=utf-8 violation)
Closed
#383 Auto-Tune: per-channel configuration (DetailPanel) — editable per-channel step
Closed
#396 Collapsible left sidebar + collapsible nav groups
Closed
#363 functional-E2E harness: add the deferred media/lock/Playwright flows (follow-up to #299)
Closed
#293 Page/cap GET /api/search/all-items (DoS hardening — deferred from #285)
Closed
#308 Concurrent same-item Add*ToCollection can 500 on composite-PK violation (pre-existing idempotency-under-concurrency gap)
Closed
#425 Auto-Tune DetailPanel: per-source rotation weights + query corrections (weighted-distribution redesign)
Closed
#176 Rethink channel/playout/schedule creation: PseudoTV-style channel-first flow with a Kodi-smart-playlist-like query builder
Closed
#386 Auto-Tune DetailPanel: per-channel editor slide-over (SPA)
Closed
#164 Health checks UX: audit usefulness + guided/automated remediation
Closed
#385 Auto-Tune DetailPanel: per-channel overrides + rotation weights in bulk-create
Closed
#320 TroubleshootController playback segment-wait loop doesn't check notifier.IsFailed (spins until client cancel if ffmpeg dies)
Closed
#416 CI: docs-only changes run the full build/test matrix (~9 min) for nothing
Closed
#376 XMLTV: access_token query value interpolated raw into guide (pre-existing XML-injection)
Closed
#70 Weighted / fair-share content distribution (playback order)
Closed
#72 Channel lineup health at-a-glance (status states in the channels list)
Closed
#406 CI: cut peak build RSS (Roslyn), cap the services: mysql, and move api-docs/format back to ubuntu-latest
Closed
#264 Local libraries always show "Never scanned" — local scanner sets path-level LastScan but not library.LastScan
Closed
#59 Backlog: full UI redesign and ChicoryTV rebrand
Closed
#384 Auto-Tune DetailPanel: enumerate a SmartCollection's distinct members (read endpoint)
Closed
#390 CI: shared toolchain base image (.NET 10 SDK + Node 22 + ffmpeg) for CI jobs
Closed
#73 Seasonal / date-conditional channels & schedule rules
Closed
#380 Refactor: shared enumerator-construction/state seam for PlaybackOrder across scheduling engines
Closed
#388 Mirror the ChicoryTV design system to prod (Claude Design ↔ shipped SPA)
Closed
#77 Pad/snap channel schedules to clock boundaries (:00/:15/:30) using filler
Closed
#69 Auto-tuning: generate channels automatically from library metadata
Closed
#357 Jellyfin/Kodi PoC: player-owned channel playback with ErsatzTV as channel engine
Closed
#71 Persistent shuffle state + explicit "Reroll" control
Closed
#163 Golden-style characterization tests for playout building
Closed
#15 Adopt a C# lint/format/static-analysis stack (the ruff equivalent) and enforce in CI
Closed
#373 bug(spa): white border around the edges of the login / boot pages (missing body margin reset)
Closed
#377 SPA: left sidebar scrolls horizontally (unwanted overflow-x)
Closed
#340 Add configurable advertised IPTV base URL for M3U/XMLTV output
Closed
#333 test: run #202 real-server media-source integration validation
Closed
#334 security: keep local-library filesystem paths authenticated when reads are open
Closed
#354 ChicoryTV: subtitles progressively run ahead of dialogue during playback
Closed
#99 Backend: track active sessions for MPEG-TS and HLS-Direct streams
Closed
#345 Plex pin flow reports connected but strands authorized accounts with no servers
Closed
#364 docs: make queue selection non-terminal
Closed
#299 CI: codify the manual live-E2E flows into an automated functional-E2E harness
Closed
#243 Refactor ChicoryTV App.tsx into screen-owned modules and a small app shell
Closed
#247 Extract ChicoryTV shell/routing and replace implicit TopBar action coupling
Closed
#246 Extract Dashboard and Guide screens from App.tsx
Closed
#355 docs: record tested Codex cheap-worker launch configuration
Closed
#353 docs: start tool-bearing selectors at low effort
Closed
#245 Extract PlayoutsScreen and playout UI helpers from App.tsx
Closed
#347 Queue selector skips milestone work and repicks completed reviewer audits
Closed
#344 Saving a remote connection falsely triggers the dirty guard
Closed
#342 Enforce session-wide low-cost routing for bounded reconnaissance
Closed
#330 Add Cross-Origin-Resource-Policy header (ZAP #314 authenticated-scan Low)
Closed
#339 docs: require low-cost queue selection preflight
Closed
#237 ChicoryTV rewrite — queue tracker (goal, arc, session protocol)
Closed
#335 release: cut v26.8.0 and complete ChicoryTV go-live
Closed
#336 docs: prepare the v26.8.0 release boundary
Closed
#197 Cold adversarial review: REST API contract + security posture (pre-ossification)
Closed
#332 docs: make ChicoryTV queue handoff client-neutral
Closed
#314 Out-of-ecosystem black-box security scan against the running container (#197 exit criterion)
Closed
#172 Scheduling API hardening follow-ups from #144 S1/S2 reviews
Closed
#286 #197 C1 [BLOCKER]: no API versioning — mount /api/v1 before the contract freezes
Closed
#238 TopBar primaryAction button is inert on every screen except SchedulesScreen
Closed
#253 Replace-all PUTs have no optimistic concurrency — stale two-tab overwrite; define a shared If-Match/version contract before more editors ossify
Closed
#265 If-Match parsing: return 412 (not 400) for syntactically-valid but non-matching entity-tags (RFC 7232 semantics)
Closed
#319 Set security response headers (CSP, X-Content-Type-Options, Permissions-Policy, COEP) on the host — ZAP baseline finding (#314 / #197 input)
Closed
#301 #295: side-effecting GET endpoints bypass the session CSRF gate (troubleshoot playback/archive) — resolve with the SPA session cutover (PR2)
Closed
#295 [PLAN-MODE] Browser SPA auth = OIDC + local login (session); demote API key to external/MCP-only — revise Bundle A posture
Closed
#315 Release path: migration-on-prod-copy smoke (restore backup → apply migrations → boot) before promoting
Closed
#317 Merge-consent gate double-prompts on the satisfied path (exit-0 allow doesn't suppress the MCP prompt) — #303 H6/H10 follow-up
Closed
#303 Process hardening: queue-drift root-cause fix + methodology review + rigor-enforcement hooks
Closed
#311 Process hardening: enforce formatting-as-you-touch + rebase-before-push (H11 + PR-scoped format CI)
Closed
#312 Process hardening: H12 — session-end issue-qualification audit
Closed
#269 #253 follow-up: same-root config sibling writers don't rotate the aggregate ETag (cross-editor invalidation)
Closed
#271 External-collections scan has no status/progress REST surface — SPA collections buttons are optimistic + timeout-bounded
Closed
#287 #197 C2/C4/C5/C6 [BLOCKER/HIGH]: OpenAPI security scheme, 401/400 docs, operationIds, DayOfWeek — by construction
Closed
#288 #197 C3+C7 [HIGH]: DTO nullability noise + raw VMs + search pageNum before freeze
Closed
#289 #197 MCP [HIGH]: harden the read-only MCP server (runtime verb-guard, JSON-crash DoS, injection framing) — PR #76
Closed
#283 #197 S4+S9 [HIGH]: stored XSS via unvalidated upload content-type reflected on serve (supersedes #66)
Closed
#285 #197 S7+S10 [MED]: mutating GETs, spoofable ForwardedHeaders, scanner exemption, unpaged all-items
Closed
#284 #197 S6 [HIGH/MED]: CORS AllowAll — drive-by cross-origin reads/writes
Closed
#282 #197 S3+S5 [HIGH]: unauthenticated GETs leak private media samples, env vars, logs, settings, FS paths
Closed
#281 #197 S2 [HIGH]: persistent mutation outside /api bypasses the write key even when configured (SortController)
Closed
#280 #197 S1 [BLOCKER]: API writes are fail-OPEN by default — no key ⇒ every mutation unauthenticated
Closed
#66 Full image-type support for logo/watermark (incl. transparent re-encode)
Closed
#278 chore(release): ship v26.7.0 (Blazor removal) to prod + revert deploy model to :prod-following
Closed
#259 Replace-all reconcile: content-aware stable child identity (moved item inherits the wrong slot's state) — split from #253
Closed
#91 ChicoryTV SPA: Blazor → SPA cutover (retire old UI)
Closed
#235 Async-op API contract normalization + playout build observability (reviewer#20 F7+F8+F9)
Closed
#149 CI flake: migrations job MySQL service publishes fixed host port 3306 — concurrent runs collide
Closed
#254 Mutation hardening cluster (audit #21/#22/#23 low-severity): post-commit token consistency, orphan guide xml, child-id stability, dirty-nav guard, empty-list semantics
Closed
#257 Plex library-preferences save releases the library lock before the network scan runs (Unlock ordering)
Closed
#256 Media-source sign-out/disconnect handlers leak their EntityLocker on exception (no finally) — permanent 409
Closed
#255 Path-replacement UPDATE SQL is not source-scoped — a PUT to source A can overwrite source B's replacement
Closed
#202 Blazor removal blocked: media-source add/edit/path-replacement has NO SPA equivalent and NO write REST API
Closed
#205 Rollback: cut and document a dedicated pre-removal Blazor tag before deletion
Closed
#206 Removal plan has no auth step: deleting the last challenged Blazor page leaves only the open SPA
Closed
#204 Redirect matcher is exact-match only: parameterized legacy routes will hard-404 after Blazor deletion (Step 1 infeasible as written)
Closed
#251 Deco-template / deco edits don't invalidate dependent playouts — editor reports success but filler/break content stays stale until a manual Reset
Closed
#252 Schedule-items PUT cascade-deletes PlayoutScheduleItemFillGroupIndex — every save (even a no-op) silently resets fill-group progression
Closed
#234 Subtitle extraction leaks all playout locks on cancellation/exception; BuildPlayout ignores lock result (reviewer#20 F4+F5.2)
Closed
#233 Troubleshooting playback lock leaks permanently on "media not on disk"; lock conflict = 404 (reviewer#20 F3)
Closed
#244 Extract ChannelsScreen from App.tsx with colocated tests
Closed
#212 SPA channel editor gaps: external logo URL, bare-channel create, enumerated pickers downgraded to free-text
Closed
#230 Schedules editor dirty-draft guard gaps: popstate navigation + shuffle-toggle normalization
Closed
#231 [PLAN-MODE] EntityLocker soundness: atomic bool locks + ownership model (reviewer#20 F5)
Closed
#232 Scan lifecycle honesty: 200-on-dropped-scan, non-finally unlocks, unguarded enqueue (reviewer#20 F1+F2+F6)
Closed
#126 API: schedule item polymorphic fields rely on implicit Newtonsoft runtime-type serialization (OpenAPI schema gap)
Closed
#207 SPA schedules editor is read-only at mutation depth — create/edit/delete + per-item editing missing (blocks #91 phase b)
Closed
#215 API playout mutations skip EntityLocker build-lock gating (delete/reset/erase race with in-flight builds)
Closed
#213 Parity nits batch: block/watermark copy UI, trash select-all/see-all, logs sort, page-size persistence, stale UI notes, decision-log entries
Closed
#217 Add-items handlers validate existence for only 4 of 10 media kinds (collections + playlists)
Closed
#218 Sidebar shows stray "Playouts 3" badge (and "1 failing" health chip) on a fresh empty DB
Closed
#219 Per-show scan API can scan the wrong show because it resolves by substring title
Closed
#220 Episode cards remain inert despite search card-navigation parity claim
Closed
#221 Search and browse mutation controls can act on stale result sets during refetch
Closed
#236 CI: EF-migration mysql service publishes host port 3306 — concurrent jobs on one runner collide
Closed
#208 SPA search screen has no mutation surface: multi-select, add-to-collection/playlist, save-as-smart-collection, card navigation (blocks #91 phase b)
Closed
#209 SPA media browse/detail: add-to-* affordances, per-show scan, per-episode info/troubleshoot entries missing (blocks #91 phase b)
Closed
#211 SPA collections: custom playback order has no endpoint/UI; add-items picker covers 4 of 10 media kinds (blocks #91 phase b)
Closed
#210 SPA playouts: unwired delete/reset endpoints, missing erase-items/history + scheduling-context, templates preview calendar (blocks #91 phase b)
Closed
#203 Parity doc is unreliable as the deletion checklist: "SPA-READY" conflates screen-exists with functional parity
Closed
#198 OpenAPI spec property casing drifts from runtime JSON for leading-acronym fields (fFmpegProfileId vs ffmpegProfileId) — ChannelEditScreen silently mis-reads profile
Closed
#193 Harden rerun-collection create/update: existence-check the selected id
Closed
#145 SPA parity: Logs & troubleshooting pages (#91 blocker)
Closed
#153 API gap: playlists/playlist groups have no REST endpoints (blocks full #140 parity / #91)
Closed
#151 API gap: multi-collections have no REST endpoints (blocks full #140 parity / #91)
Closed
#152 API gap: rerun collections have no REST endpoints (blocks full #140 parity / #91)
Closed
#190 CI speed: cache NuGet packages (+ minor Docker/checkout wins)
Closed
#155 API gap: no endpoint lists a manual collection's items (GET /api/collections/{id}/items)
Closed
#184 ApiControllerSecurityTests registry has drifted: 9 controllers unlisted (2 with mutating verbs) — replace hardcoded array with assembly scanning
Closed
#185 Onboarding docs, part 2: testing map + generated endpoint index (HIGH PRIORITY, next session)
Closed
#141 SPA parity: Media browsing, search & trash (#91 blocker)
Closed
#161 API gap: media browse (all kinds), search, detail, delete, image folders (#141 blocker)
Closed
#158 API gap: logs + troubleshooting endpoints (#145 blocker)
Closed
#180 Channel Builder library picker: one tile per season floods the grid — group seasons under their show
Closed
#162 API gap: scheduling REST surface — blocks/decos/templates/deco-templates + playout create/detail editors (#144 blocker)
Closed
#144 SPA parity: Scheduling building blocks + playout detail editors (#91 blocker)
Closed
#157 Flaky web test: 'stops Libraries scan polling and refreshes sources once when scans complete' (App.test.tsx)
Closed
#160 API gap: Trakt lists controller (#142 blocker)
Closed
#142 SPA parity: Trakt lists (#91 blocker)
Closed
#159 API gap: filler preset + watermark editor CRUD; FFmpeg profile response DTO round-trip (#143 blocker)
Closed
#143 SPA parity: FFmpeg profiles, filler presets, watermarks editors (#91 blocker)
Closed
#140 SPA parity: Collections management screen (#91 blocker)
Closed
#146 SPA parity: Channel edit + channel numbers (#91 blocker)
Closed
#147 SPA: discoverable link to the legacy Blazor UI while parity gaps remain (#91 follow-up)
Closed
#90 ChicoryTV SPA: rebrand assets + naming
Closed
#93 ChicoryTV SPA: Settings screen (prototype → implement)
Closed
#92 Enable /design-sync round-trip (Claude Design ↔ repo, no zip)
Closed
#89 ChicoryTV SPA: Channel Builder (primary deliverable)
Closed
#63 Composite "create channel from lineup" endpoint
Closed
#64 Channel Templates (built-in + custom) bundling technical/behavioral defaults
Closed
#65 Library browse + search API with artwork (for the create-channel picker)
Closed
#85 ChicoryTV SPA: Guide / EPG screen
Closed
#88 ChicoryTV SPA: Libraries screen
Closed
#87 ChicoryTV SPA: Playouts screen
Closed
#86 ChicoryTV SPA: Schedule editor screen
Closed
#84 ChicoryTV SPA: Channels screen
Closed
#109 ChicoryTV SPA: Dashboard follow-up — replace stubbed data with real sources
Closed
#97 Backend: channel on-air / now-playing state API (for Channels screen live treatment)
Closed
#102 Backend: JSON channel-guide endpoint for the EPG grid
Closed
#111 Backend: schedule item duration estimates + schedule total
Closed
#104 Backend: logo/watermark image upload endpoint
Closed
#103 Backend: media sources + libraries read model (GET /api/media-sources)
Closed
#106 Backend: library scan status/progress endpoint
Closed
#101 Backend: GET /api/playouts/{id}/items endpoint
Closed
#107 Backend: playout build status + warnings count in the API
Closed
#110 Backend: playout reset-all endpoint + reset-mode reconciliation
Closed
#100 Backend: GET /api/playouts (list) endpoint
Closed
#108 Backend: expose health checks via REST (GET /api/health)
Closed
#105 Backend: list endpoints for filler presets, watermarks, graphics elements
Closed
#98 Backend: bulk channel operations API (renumber, move to group, bulk delete)
Closed
#96 Backend: extend channel list API for the management table (group, enabled, EPG visibility)
Closed
#95 Fix SPA foundation review findings (#78-#81 follow-up)
Closed
#94 Fix app-shell review findings (#82 follow-up)
Closed
#83 ChicoryTV SPA: Dashboard screen
Closed
#82 ChicoryTV SPA: app shell (sidebar + top bar + routing)
Closed
#81 ChicoryTV SPA: typed API client + auth
Closed
#80 ChicoryTV SPA: component library (primitives)
Closed
#79 ChicoryTV SPA: design tokens + 3 themes
Closed
#78 ChicoryTV SPA: scaffold + build integration
Closed
#3 CI/CD pipeline and test/prod environments
Closed
#57 chore: stop tracking local MCP config
Closed
#9 FFmpeg 8 compatibility (app-side) for transcode pipelines
Closed
#42 Implement Jellyfin MusicVideo library sync (currently silently dropped)
Closed
#43 API write-auth: decide a global default-deny model for all /api/* mutating endpoints
Closed
#39 test: make ChannelLogoGenerator testable (inject overlay/font paths) for a channel-logo property test
Closed
#2 Build REST API for channel/collection/schedule CRUD
Closed
#38 REST API #2e: Standardization cleanup (retrofit FFmpegProfileController, OpenAPI/CORS/docs)
Closed
#37 REST API #2d: Playouts create/delete
Closed
#36 REST API #2c: Schedules CRUD + schedule items (TPT-heavy)
Closed
#46 REST API: standardize error response body contract
Closed
#35 REST API #2b: Collections CRUD + items (+ retrofit SmartCollectionController)
Closed
#34 REST API #2a: API foundation + Channels CRUD (pattern-setter)
Closed
#24 2 PlayoutModeSchedulerBase filler tests fail under non-UTC local timezones
Closed
#28 Golden tests for XMLTV guide + channel-logo output (follow-up to #11)
Closed
#5 Jellyfin removes ErsatzTV items during library scan (MTV Unplugged)
Closed
#1 Fix M3U tvg-logo URLs hardcoding localhost
Closed
#10 Write a retroactive contributors / style guide capturing established patterns
Closed
#16 Container E2E: assert key IPTV endpoints on the built image
Closed
#13 CI checks for EF Core migration integrity (SQLite + MySql)
Closed
#11 Golden-file tests for M3U / XMLTV / channel-logo output
Closed
#12 Enforce architecture / layering with tests
Closed
#8 Update vulnerable transitive dependencies (NuGet audit advisories)
Closed
#14 Dependency hygiene: scheduled vulnerability scan + Central Package Management
Closed
#4 Set up Gitea Actions Docker build workflow
Closed
#7 Slim memory files — move reference content to in-repo docs
Closed
#6 Missing architecture docs: channel management, M3U generation, logo fixes
466 Issues created by 2 users
Opened
#5 Jellyfin removes ErsatzTV items during library scan (MTV Unplugged)
Opened
#6 Missing architecture docs: channel management, M3U generation, logo fixes
Opened
#7 Slim memory files — move reference content to in-repo docs
Opened
#8 Update vulnerable transitive dependencies (NuGet audit advisories)
Opened
#9 FFmpeg 8 compatibility (app-side) for transcode pipelines
Opened
#10 Write a retroactive contributors / style guide capturing established patterns
Opened
#11 Golden-file tests for M3U / XMLTV / channel-logo output
Opened
#12 Enforce architecture / layering with tests
Opened
#13 CI checks for EF Core migration integrity (SQLite + MySql)
Opened
#14 Dependency hygiene: scheduled vulnerability scan + Central Package Management
Opened
#15 Adopt a C# lint/format/static-analysis stack (the ruff equivalent) and enforce in CI
Opened
#16 Container E2E: assert key IPTV endpoints on the built image
Opened
#22 Dependency Dashboard
Opened
#24 2 PlayoutModeSchedulerBase filler tests fail under non-UTC local timezones
Opened
#25 Burn down SonarAnalyzer findings in Blazor .razor (analyzer adoption #15)
Opened
#28 Golden tests for XMLTV guide + channel-logo output (follow-up to #11)
Opened
#34 REST API #2a: API foundation + Channels CRUD (pattern-setter)
Opened
#35 REST API #2b: Collections CRUD + items (+ retrofit SmartCollectionController)
Opened
#36 REST API #2c: Schedules CRUD + schedule items (TPT-heavy)
Opened
#37 REST API #2d: Playouts create/delete
Opened
#38 REST API #2e: Standardization cleanup (retrofit FFmpegProfileController, OpenAPI/CORS/docs)
Opened
#39 test: make ChannelLogoGenerator testable (inject overlay/font paths) for a channel-logo property test
Opened
#42 Implement Jellyfin MusicVideo library sync (currently silently dropped)
Opened
#43 API write-auth: decide a global default-deny model for all /api/* mutating endpoints
Opened
#46 REST API: standardize error response body contract
Opened
#57 chore: stop tracking local MCP config
Opened
#58 Backlog: MCP server for ErsatzTV/ChicoryTV API
Opened
#59 Backlog: full UI redesign and ChicoryTV rebrand
Opened
#60 Backlog: browser channel playback after UI redesign
Opened
#62 Epic: Create Channel — backend prerequisites for the redesigned creation flow
Opened
#63 Composite "create channel from lineup" endpoint
Opened
#64 Channel Templates (built-in + custom) bundling technical/behavioral defaults
Opened
#65 Library browse + search API with artwork (for the create-channel picker)
Opened
#66 Full image-type support for logo/watermark (incl. transparent re-encode)
Opened
#67 Unified logo/bug image handling (one image drives both, separable)
Opened
#68 Resume/bookmark playback position for sequential channels (personal continue-watching)
Opened
#69 Auto-tuning: generate channels automatically from library metadata
Opened
#70 Weighted / fair-share content distribution (playback order)
Opened
#71 Persistent shuffle state + explicit "Reroll" control
Opened
#72 Channel lineup health at-a-glance (status states in the channels list)
Opened
#73 Seasonal / date-conditional channels & schedule rules
Opened
#74 [Blue sky] On-screen "On Now / On Next" overlay (channel-surf bug)
Opened
#75 [Blue sky] Themed "Resource Packs" for bumpers / branding / interstitials
Opened
#77 Pad/snap channel schedules to clock boundaries (:00/:15/:30) using filler
Opened
#78 ChicoryTV SPA: scaffold + build integration
Opened
#79 ChicoryTV SPA: design tokens + 3 themes
Opened
#80 ChicoryTV SPA: component library (primitives)
Opened
#81 ChicoryTV SPA: typed API client + auth
Opened
#82 ChicoryTV SPA: app shell (sidebar + top bar + routing)
Opened
#83 ChicoryTV SPA: Dashboard screen
Opened
#84 ChicoryTV SPA: Channels screen
Opened
#85 ChicoryTV SPA: Guide / EPG screen
Opened
#86 ChicoryTV SPA: Schedule editor screen
Opened
#87 ChicoryTV SPA: Playouts screen
Opened
#88 ChicoryTV SPA: Libraries screen
Opened
#89 ChicoryTV SPA: Channel Builder (primary deliverable)
Opened
#90 ChicoryTV SPA: rebrand assets + naming
Opened
#91 ChicoryTV SPA: Blazor → SPA cutover (retire old UI)
Opened
#92 Enable /design-sync round-trip (Claude Design ↔ repo, no zip)
Opened
#93 ChicoryTV SPA: Settings screen (prototype → implement)
Opened
#94 Fix app-shell review findings (#82 follow-up)
Opened
#95 Fix SPA foundation review findings (#78-#81 follow-up)
Opened
#96 Backend: extend channel list API for the management table (group, enabled, EPG visibility)
Opened
#97 Backend: channel on-air / now-playing state API (for Channels screen live treatment)
Opened
#98 Backend: bulk channel operations API (renumber, move to group, bulk delete)
Opened
#99 Backend: track active sessions for MPEG-TS and HLS-Direct streams
Opened
#100 Backend: GET /api/playouts (list) endpoint
Opened
#101 Backend: GET /api/playouts/{id}/items endpoint
Opened
#102 Backend: JSON channel-guide endpoint for the EPG grid
Opened
#103 Backend: media sources + libraries read model (GET /api/media-sources)
Opened
#104 Backend: logo/watermark image upload endpoint
Opened
#105 Backend: list endpoints for filler presets, watermarks, graphics elements
Opened
#106 Backend: library scan status/progress endpoint
Opened
#107 Backend: playout build status + warnings count in the API
Opened
#108 Backend: expose health checks via REST (GET /api/health)
Opened
#109 ChicoryTV SPA: Dashboard follow-up — replace stubbed data with real sources
Opened
#110 Backend: playout reset-all endpoint + reset-mode reconciliation
Opened
#111 Backend: schedule item duration estimates + schedule total
Opened
#126 API: schedule item polymorphic fields rely on implicit Newtonsoft runtime-type serialization (OpenAPI schema gap)
Opened
#135 from-lineup advanced overrides cannot express "clear to none" (null = inherit template)
Opened
#140 SPA parity: Collections management screen (#91 blocker)
Opened
#141 SPA parity: Media browsing, search & trash (#91 blocker)
Opened
#142 SPA parity: Trakt lists (#91 blocker)
Opened
#143 SPA parity: FFmpeg profiles, filler presets, watermarks editors (#91 blocker)
Opened
#144 SPA parity: Scheduling building blocks + playout detail editors (#91 blocker)
Opened
#145 SPA parity: Logs & troubleshooting pages (#91 blocker)
Opened
#146 SPA parity: Channel edit + channel numbers (#91 blocker)
Opened
#147 SPA: discoverable link to the legacy Blazor UI while parity gaps remain (#91 follow-up)
Opened
#149 CI flake: migrations job MySQL service publishes fixed host port 3306 — concurrent runs collide
Opened
#151 API gap: multi-collections have no REST endpoints (blocks full #140 parity / #91)
Opened
#152 API gap: rerun collections have no REST endpoints (blocks full #140 parity / #91)
Opened
#153 API gap: playlists/playlist groups have no REST endpoints (blocks full #140 parity / #91)
Opened
#155 API gap: no endpoint lists a manual collection's items (GET /api/collections/{id}/items)
Opened
#157 Flaky web test: 'stops Libraries scan polling and refreshes sources once when scans complete' (App.test.tsx)
Opened
#158 API gap: logs + troubleshooting endpoints (#145 blocker)
Opened
#159 API gap: filler preset + watermark editor CRUD; FFmpeg profile response DTO round-trip (#143 blocker)
Opened
#160 API gap: Trakt lists controller (#142 blocker)
Opened
#161 API gap: media browse (all kinds), search, detail, delete, image folders (#141 blocker)
Opened
#162 API gap: scheduling REST surface — blocks/decos/templates/deco-templates + playout create/detail editors (#144 blocker)
Opened
#163 Golden-style characterization tests for playout building
Opened
#164 Health checks UX: audit usefulness + guided/automated remediation
Opened
#172 Scheduling API hardening follow-ups from #144 S1/S2 reviews
Opened
#176 Rethink channel/playout/schedule creation: PseudoTV-style channel-first flow with a Kodi-smart-playlist-like query builder
Opened
#177 Jellyfin music video sync: map Album/Track metadata (credits-overlay completeness)
Opened
#178 Idea (far future): Jellyfin plugin to control ErsatzTV from within Jellyfin
Opened
#180 Channel Builder library picker: one tile per season floods the grid — group seasons under their show
Opened
#184 ApiControllerSecurityTests registry has drifted: 9 controllers unlisted (2 with mutating verbs) — replace hardcoded array with assembly scanning
Opened
#185 Onboarding docs, part 2: testing map + generated endpoint index (HIGH PRIORITY, next session)
Opened
#190 CI speed: cache NuGet packages (+ minor Docker/checkout wins)
Opened
#193 Harden rerun-collection create/update: existence-check the selected id
Opened
#197 Cold adversarial review: REST API contract + security posture (pre-ossification)
Opened
#198 OpenAPI spec property casing drifts from runtime JSON for leading-acronym fields (fFmpegProfileId vs ffmpegProfileId) — ChannelEditScreen silently mis-reads profile
Opened
#202 Blazor removal blocked: media-source add/edit/path-replacement has NO SPA equivalent and NO write REST API
Opened
#203 Parity doc is unreliable as the deletion checklist: "SPA-READY" conflates screen-exists with functional parity
Opened
#204 Redirect matcher is exact-match only: parameterized legacy routes will hard-404 after Blazor deletion (Step 1 infeasible as written)
Opened
#205 Rollback: cut and document a dedicated pre-removal Blazor tag before deletion
Opened
#206 Removal plan has no auth step: deleting the last challenged Blazor page leaves only the open SPA
Opened
#207 SPA schedules editor is read-only at mutation depth — create/edit/delete + per-item editing missing (blocks #91 phase b)
Opened
#208 SPA search screen has no mutation surface: multi-select, add-to-collection/playlist, save-as-smart-collection, card navigation (blocks #91 phase b)
Opened
#209 SPA media browse/detail: add-to-* affordances, per-show scan, per-episode info/troubleshoot entries missing (blocks #91 phase b)
Opened
#210 SPA playouts: unwired delete/reset endpoints, missing erase-items/history + scheduling-context, templates preview calendar (blocks #91 phase b)
Opened
#211 SPA collections: custom playback order has no endpoint/UI; add-items picker covers 4 of 10 media kinds (blocks #91 phase b)
Opened
#212 SPA channel editor gaps: external logo URL, bare-channel create, enumerated pickers downgraded to free-text
Opened
#213 Parity nits batch: block/watermark copy UI, trash select-all/see-all, logs sort, page-size persistence, stale UI notes, decision-log entries
Opened
#215 API playout mutations skip EntityLocker build-lock gating (delete/reset/erase race with in-flight builds)
Opened
#217 Add-items handlers validate existence for only 4 of 10 media kinds (collections + playlists)
Opened
#218 Sidebar shows stray "Playouts 3" badge (and "1 failing" health chip) on a fresh empty DB
Opened
#219 Per-show scan API can scan the wrong show because it resolves by substring title
Opened
#220 Episode cards remain inert despite search card-navigation parity claim
Opened
#221 Search and browse mutation controls can act on stale result sets during refetch
Opened
#230 Schedules editor dirty-draft guard gaps: popstate navigation + shuffle-toggle normalization
Opened
#231 [PLAN-MODE] EntityLocker soundness: atomic bool locks + ownership model (reviewer#20 F5)
Opened
#232 Scan lifecycle honesty: 200-on-dropped-scan, non-finally unlocks, unguarded enqueue (reviewer#20 F1+F2+F6)
Opened
#233 Troubleshooting playback lock leaks permanently on "media not on disk"; lock conflict = 404 (reviewer#20 F3)
Opened
#234 Subtitle extraction leaks all playout locks on cancellation/exception; BuildPlayout ignores lock result (reviewer#20 F4+F5.2)
Opened
#235 Async-op API contract normalization + playout build observability (reviewer#20 F7+F8+F9)
Opened
#236 CI: EF-migration mysql service publishes host port 3306 — concurrent jobs on one runner collide
Opened
#237 ChicoryTV rewrite — queue tracker (goal, arc, session protocol)
Opened
#238 TopBar primaryAction button is inert on every screen except SchedulesScreen
Opened
#243 Refactor ChicoryTV App.tsx into screen-owned modules and a small app shell
Opened
#244 Extract ChannelsScreen from App.tsx with colocated tests
Opened
#245 Extract PlayoutsScreen and playout UI helpers from App.tsx
Opened
#246 Extract Dashboard and Guide screens from App.tsx
Opened
#247 Extract ChicoryTV shell/routing and replace implicit TopBar action coupling
Opened
#248 SPA dialogs (overlay.tsx) are not focus-trapped / background-inerted
Opened
#251 Deco-template / deco edits don't invalidate dependent playouts — editor reports success but filler/break content stays stale until a manual Reset
Opened
#252 Schedule-items PUT cascade-deletes PlayoutScheduleItemFillGroupIndex — every save (even a no-op) silently resets fill-group progression
Opened
#253 Replace-all PUTs have no optimistic concurrency — stale two-tab overwrite; define a shared If-Match/version contract before more editors ossify
Opened
#254 Mutation hardening cluster (audit #21/#22/#23 low-severity): post-commit token consistency, orphan guide xml, child-id stability, dirty-nav guard, empty-list semantics
Opened
#255 Path-replacement UPDATE SQL is not source-scoped — a PUT to source A can overwrite source B's replacement
Opened
#256 Media-source sign-out/disconnect handlers leak their EntityLocker on exception (no finally) — permanent 409
Opened
#257 Plex library-preferences save releases the library lock before the network scan runs (Unlock ordering)
Opened
#259 Replace-all reconcile: content-aware stable child identity (moved item inherits the wrong slot's state) — split from #253
Opened
#264 Local libraries always show "Never scanned" — local scanner sets path-level LastScan but not library.LastScan
Opened
#265 If-Match parsing: return 412 (not 400) for syntactically-valid but non-matching entity-tags (RFC 7232 semantics)
Opened
#269 #253 follow-up: same-root config sibling writers don't rotate the aggregate ETag (cross-editor invalidation)
Opened
#271 External-collections scan has no status/progress REST surface — SPA collections buttons are optimistic + timeout-bounded
Opened
#278 chore(release): ship v26.7.0 (Blazor removal) to prod + revert deploy model to :prod-following
Opened
#280 #197 S1 [BLOCKER]: API writes are fail-OPEN by default — no key ⇒ every mutation unauthenticated
Opened
#281 #197 S2 [HIGH]: persistent mutation outside /api bypasses the write key even when configured (SortController)
Opened
#282 #197 S3+S5 [HIGH]: unauthenticated GETs leak private media samples, env vars, logs, settings, FS paths
Opened
#283 #197 S4+S9 [HIGH]: stored XSS via unvalidated upload content-type reflected on serve (supersedes #66)
Opened
#284 #197 S6 [HIGH/MED]: CORS AllowAll — drive-by cross-origin reads/writes
Opened
#285 #197 S7+S10 [MED]: mutating GETs, spoofable ForwardedHeaders, scanner exemption, unpaged all-items
Opened
#286 #197 C1 [BLOCKER]: no API versioning — mount /api/v1 before the contract freezes
Opened
#287 #197 C2/C4/C5/C6 [BLOCKER/HIGH]: OpenAPI security scheme, 401/400 docs, operationIds, DayOfWeek — by construction
Opened
#288 #197 C3+C7 [HIGH]: DTO nullability noise + raw VMs + search pageNum before freeze
Opened
#289 #197 MCP [HIGH]: harden the read-only MCP server (runtime verb-guard, JSON-crash DoS, injection framing) — PR #76
Opened
#293 Page/cap GET /api/search/all-items (DoS hardening — deferred from #285)
Opened
#295 [PLAN-MODE] Browser SPA auth = OIDC + local login (session); demote API key to external/MCP-only — revise Bundle A posture
Opened
#297 Add channelId to PlayoutListItemResponseModel so the SPA reset button keys directly
Opened
#299 CI: codify the manual live-E2E flows into an automated functional-E2E harness
Opened
#301 #295: side-effecting GET endpoints bypass the session CSRF gate (troubleshoot playback/archive) — resolve with the SPA session cutover (PR2)
Opened
#303 Process hardening: queue-drift root-cause fix + methodology review + rigor-enforcement hooks
Opened
#308 Concurrent same-item Add*ToCollection can 500 on composite-PK violation (pre-existing idempotency-under-concurrency gap)
Opened
#310 De-BOM the 17 legacy .cs files #269 touched (charset=utf-8 violation)
Opened
#311 Process hardening: enforce formatting-as-you-touch + rebase-before-push (H11 + PR-scoped format CI)
Opened
#312 Process hardening: H12 — session-end issue-qualification audit
Opened
#314 Out-of-ecosystem black-box security scan against the running container (#197 exit criterion)
Opened
#315 Release path: migration-on-prod-copy smoke (restore backup → apply migrations → boot) before promoting
Opened
#317 Merge-consent gate double-prompts on the satisfied path (exit-0 allow doesn't suppress the MCP prompt) — #303 H6/H10 follow-up
Opened
#319 Set security response headers (CSP, X-Content-Type-Options, Permissions-Policy, COEP) on the host — ZAP baseline finding (#314 / #197 input)
Opened
#320 TroubleshootController playback segment-wait loop doesn't check notifier.IsFailed (spins until client cancel if ffmpeg dies)
Opened
#327 Playlist rename (ReplacePlaylistItems) does no name validation — empty / >50-char names accepted
Opened
#330 Add Cross-Origin-Resource-Policy header (ZAP #314 authenticated-scan Low)
Opened
#332 docs: make ChicoryTV queue handoff client-neutral
Opened
#333 test: run #202 real-server media-source integration validation
Opened
#334 security: keep local-library filesystem paths authenticated when reads are open
Opened
#335 release: cut v26.8.0 and complete ChicoryTV go-live
Opened
#336 docs: prepare the v26.8.0 release boundary
Opened
#338 ci: distinguish ZAP warning exit 2 from FAIL in security-scan
Opened
#339 docs: require low-cost queue selection preflight
Opened
#340 Add configurable advertised IPTV base URL for M3U/XMLTV output
Opened
#342 Enforce session-wide low-cost routing for bounded reconnaissance
Opened
#344 Saving a remote connection falsely triggers the dirty guard
Opened
#345 Plex pin flow reports connected but strands authorized accounts with no servers
Opened
#347 Queue selector skips milestone work and repicks completed reviewer audits
Opened
#350 Channel cold-start ~7s to first segment — slow tune-in via Dispatcharr/Kodi (heavy transcode profile)
Opened
#353 docs: start tool-bearing selectors at low effort
Opened
#354 ChicoryTV: subtitles progressively run ahead of dialogue during playback
Opened
#355 docs: record tested Codex cheap-worker launch configuration
Opened
#357 Jellyfin/Kodi PoC: player-owned channel playback with ErsatzTV as channel engine
Opened
#363 functional-E2E harness: add the deferred media/lock/Playwright flows (follow-up to #299)
Opened
#364 docs: make queue selection non-terminal
Opened
#367 Plex: budget-exhausted message says "Use Refresh" but there is no global Refresh when zero servers exist
Opened
#373 bug(spa): white border around the edges of the login / boot pages (missing body margin reset)
Opened
#376 XMLTV: access_token query value interpolated raw into guide (pre-existing XML-injection)
Opened
#377 SPA: left sidebar scrolls horizontally (unwanted overflow-x)
Opened
#380 Refactor: shared enumerator-construction/state seam for PlaybackOrder across scheduling engines
Opened
#381 Golden characterization tests for remaining scheduler kinds (Sequential YAML + Scripted)
Opened
#383 Auto-Tune: per-channel configuration (DetailPanel) — editable per-channel step
Opened
#384 Auto-Tune DetailPanel: enumerate a SmartCollection's distinct members (read endpoint)
Opened
#385 Auto-Tune DetailPanel: per-channel overrides + rotation weights in bulk-create
Opened
#386 Auto-Tune DetailPanel: per-channel editor slide-over (SPA)
Opened
#388 Mirror the ChicoryTV design system to prod (Claude Design ↔ shipped SPA)
Opened
#390 CI: shared toolchain base image (.NET 10 SDK + Node 22 + ffmpeg) for CI jobs
Opened
#392 Clock-align convenience: one-click per-channel/schedule pad-to-boundary toggle + 60-min increment (SPA)
Opened
#395 Refactor: dedup Scripted≡YAML enumerator construction (deferred from #380, gated on #381 goldens)
Opened
#396 Collapsible left sidebar + collapsible nav groups
Opened
#398 CI: build once, reuse artifacts across test / migrations / functional-e2e (742s of redundant compilation per run)
Opened
#401 UpdateChannel silently coerces Mirror→Generated when the channel has a playout (should be 422)
Opened
#403 Scheduling: an unhandled PlaybackOrder fails silently at five of six dispatch sites
Opened
#404 SPA: per-source weight inputs + fair-share toggle in the schedule editor (#70 UI)
Opened
#406 CI: cut peak build RSS (Roslyn), cap the services: mysql, and move api-docs/format back to ubuntu-latest
Opened
#409 Never-scanned local libraries render "Last scan 12:00 AM" instead of "Never scanned" (LastScan seeded as DateTime.MinValue, not NULL)
Opened
#410 Scan cancellation is logged at ERROR ("Scan was canceled") across all four scan handlers
Opened
#412 CI: peak-memory instrument reports cache-inflated memory.peak; sample true peak anon instead
Opened
#414 Channels list: distinguish auto-tuned from user-created channels (origin marker)
Opened
#415 Per-channel fault detection beyond "no playout" (empty schedule, broken source)
Opened
#416 CI: docs-only changes run the full build/test matrix (~9 min) for nothing
Opened
#420 CI: PR run and merge-to-main run re-execute the full matrix over identical code
Opened
#421 M3U: access_token value not quote-safe in url-tvg="..." attribute
Opened
#425 Auto-Tune DetailPanel: per-source rotation weights + query corrections (weighted-distribution redesign)
Opened
#431 Backend: TTL-cache PerformHealthChecks (GET /api/v1/health re-runs 14 checks, 4 shell out to ffmpeg, per request)
Opened
#434 Rule builder: facet-value typeahead for text fields (#176 follow-up)
Opened
#435 Rule builder: relative-date operators ("in the last N days") (#176 follow-up)
Opened
#436 Rule builder: support nesting deeper than one level (#176 follow-up)
Opened
#437 Adopt RuleBuilder inline in ChannelBuilder & Auto-Tune (#176 follow-up)
Opened
#438 Rule builder: input validation & polish (bundles #176 review minors)
Opened
#440 Auto-Tune DetailPanel SPA: wire per-source weight steppers + exclude/add-untagged to the #425 backend
Opened
#444 functional-E2E: add the playout-build lock 409 + isLocked projection flow (deferred from #363)
Opened
#445 functional-E2E: add the UI-interactive Playwright (headless) flows (deferred from #363)
Opened
#447 Flaky SPA test: LibrariesScreen "stops scan polling and refreshes sources once when scans complete"
Opened
#458 Playlist/group rename should reject duplicate names (like create does) — #327 follow-up
Opened
#460 MediaSourceRepository writes MinValue LastScan on disable-sync — normalize to null (#409 follow-up)
Opened
#463 Schedules screen: "Active schedule" selector stretches full-width and overlaps the header
Opened
#464 Guide + channels list show generated fallback icons instead of the actual channel logo
Opened
#469 CI: speed up the Formatting job (dotnet format --include still loads the whole solution)
Opened
#472 Split HLS cold-start startup phase into spawn / input-open+probe / first-GOP
Opened
#473 Tune-in hard-fails (ffmpeg exit 8) when a playout item's media file no longer exists — 717 stale episodes across 10 removed shows on prod
Opened
#474 Music channels dead: Music Videos library has no LibraryPath, so /data/music (30 folders) is never scanned — 8+ collections empty
Opened
#476 Scanner: FileNotFound does not cascade show → seasons → episodes, so playouts keep scheduling episodes of shows deleted upstream
Opened
#477 Scanner has no anti-nuke guard: a successful-but-empty media-server fetch flags an entire library FileNotFound
Opened
#478 Channels 102/107 repeatedly fail to tune: h264_vaapi hwupload -22 / exit 234 on prod
Opened
#480 External-JSON playout channels still hand ffmpeg an unprobed remote-stream URL (#473 class survives there)
Opened
#484 Media-server scanner: ratio-threshold + projection-failure detection for the empty-fetch guard
Opened
#485 Build hygiene: .gitignore core entry silently ignores new files under any Core/ directory (case-insensitive on macOS)
Opened
#487 MCP acceptance case: populate the empty music collections via the MCP write path (not by hand)
Opened
#488 JellyfinMusicVideoLibraryScanner crashes immediately: ArgumentNullException from null LibraryPath.LibraryFolders (feature has never worked)
Opened
#489 Support Jellyfin mixed-content libraries (currently dropped silently) — keep music/standup segregated from Movies & TV Shows
Opened
#491 LibraryFolder has no unique index on (LibraryPathId, Path) — concurrent GetOrAddFolder can insert duplicates
Opened
#494 JellyfinMusicVideoLibraryScanner does no reconciliation — music videos removed from Jellyfin are never removed from ErsatzTV
Opened
#496 Music videos have no per-library identity — global GetOrAdd path dedup can cross-library false-trash
Opened
#497 JellyfinMusicVideoLibraryScanner.UpdateMetadata drops Tags/Genres/Studios on existing items — Jellyfin metadata edits never sync
Opened
#498 FFmpeg profile should allow separate decode and encode hardware acceleration (QSV encode + VAAPI decode)
Opened
#500 MediaServer metadata reconcile double-inserts on duplicate collection names (Plex movie + Jellyfin music-video update paths)
Opened
#502 External-URL channel logos never render an on-screen bug (File.Exists against a URL in WatermarkSelector)
Opened
#503 Watermark MiddleCenter renders bottom-right — missing switch arm in OverlayWatermarkFilter
Opened
#505 QSV native-decode path tonemaps HDR in software (route through tonemap_qsv)
Opened
#508 Move the two docker build jobs off the small runner lane
Opened
#510 WatermarkSelector: the deco path has a different missing-logo policy than the three precedence levels
Opened
#511 Harden remote-image fetching in the graphics engine (timeout, size cap, redirects, pooling, caching, SSRF)
Opened
#512 Make LibrariesScreen scan-complete test deterministic (stop racing real microtasks under waitFor)
Opened
#515 release: cut and promote v26.11.0 to prod (first release on jazz)
Opened
#519 Verify the #350 cold-start burst end-to-end on test, then re-measure on prod
Opened
#520 Retire #237 from startup; run orientation and mechanical top-five selection in parallel
Opened
#521 Make decision knowledge lifecycle-addressable and retrieval-efficient
Opened
#523 QSV native-decode (#498) hwupload fails to allocate a QSV surface for certain content — "Cannot allocate memory" kills the stream
Opened
#524 Retrofit #237's durable-only facts into #521 decision records (post-arc follow-up)
Opened
#525 External channel-logo URLs: download + cache at save time instead of fetching at render time
Opened
#529 QSV extra_hw_frames=0 kills transcodes on any unthrottled read — live in prod, and made near-deterministic by #516's burst
Opened
#532 Re-measure HLS cold start on prod after v26.12.0+ ships the #529 floor, against #350's 13-sample baseline
Opened
#533 scripts/e2e-local.sh readiness probe hangs on a reused config dir
Opened
#535 Release-tag builds: small-lane PR-only gate jobs run + fail on v* tag pushes
Opened
#536 workAheadSegmenterLimit is not enforced: the slot check and its increment straddle an await (N concurrent tune-ins all run unthrottled)
Opened
#539 WorkAheadSlots.Release hardening: never go negative, and surface UnbalancedReleases somewhere a human will see it
Opened
#541 H13: session-end must leave the shared checkout fresh — a stale tree serves stale FILES, which no HEAD-reading rule catches
Opened
#542 The kickoff handoff doc should be instructions, not incident history — prune the narrative into decisions.md
Opened
#545 decisions-guard: require a **Signals:** line (MemPalace recall metadata contract)
Opened
#548 docs: the ersatztv skill described archived upstream, not this fork
Opened
#552 Mint a short-lived JWT for the SPA so /iptv/* works under JWT-enabled deployments
Opened
#553 select-queue.sh ranks Renovate's bot-authored Dependency Dashboard (#22) as a workable pickup
Opened
#554 Channel preview can sit at "starting" when autoplay is blocked, with no hint to press play
Opened
#559 Harden the /iptv ?access_token= transport: redact from request logs + no-store on tokened manifests
Opened
#563 Scripted playout: integration-test harness (deferred from #381 golden net)
Opened
#565 [Blue sky] Bridge Auto-Tune → Scripted: an "escape hatch" from a generated channel into a custom script
Opened
#567 Harden channel graphicsElementIds: validate unknown ids (422 not 500) + builtIn discriminator (#74 follow-up)
Opened
#568 Harden channel graphicsElementIds: validate unknown ids (422 not 500) + builtIn discriminator (#74 follow-up)
Opened
#570 On Now/Next overlay YAML fails to render (format_datetime arity + null font_family) — #74 hotfix
Opened
#572 CustomFontMapper crashes on a null font_family instead of using the default font
Opened
#578 #434 follow-ups: typeahead combobox polish + source limitations
Opened
#580 Auto-Tune: generalize the fixed axis picker into an arbitrary group-by field builder (backend, #437 split)
Opened
#582 flaky: LibrariesScreen "stops scan polling and refreshes sources once when scans complete" still non-deterministic (#512 fix incomplete)
Opened
#583 Kickoff: make per-agent model routing a hard constraint + a PreToolUse gate
Opened
#586 E2E briefs: scope process cleanup by PID, never a pattern-wide pkill
Opened
#587 chore(docs): trim derivable content from CLAUDE.md and lazy-load the task-completion protocol
Opened
#590 Auto-Tune source rows: share the Lucene escaper, warn on exclude-all, handle >50-source axes
Opened
#592 CI monitors: record that skipped is not red (build skips on every PR)
Opened
#594 ci-image-pin accepts any hex length, not the exact 7-char tag ci-image.yml publishes
Opened
#595 Active decisions corpus is at its 5600-line budget — schedule the consolidation
Opened
#596 PID-scope the Playwright-MCP stall recovery — pkill -f ms-playwright-mcp is the same shared-host reap as #586
Opened
#597 ci-image.yml should tag with --short=7 so the 7-char pin length is an enforced invariant, not an observed one
Opened
#600 Remove-stale + add-new reconcile idiom: 8 further copies still double-insert on duplicate names (#500 follow-up)
Opened
#603 decisions: adopt OKF's stale-after and Sources: as optional record metadata
Opened
#604 Collection membership rebuild has no projection-failure guard — a swallowed drop silently empties a collection
Opened
#606 One MediaItem row per file path globally — a second library serving the same file never gets its own row
Opened
#608 GetParentFolderId bypasses GetFolder — case-insensitive parent resolution can distort the folder tree on MySQL
Opened
#609 decisions-validate: [decisions-edit] is a bare substring match — a commit that merely *describes* the token disarms the guard
Opened
#610 decisions: split the monolithic corpus into one YAML-frontmatter file per record
Opened
#615 Jellyfin merges <Base> - <variant>.mp4 music videos into one multi-version item — Behind the Music (61 files) and Top of the Pops (24 files) each land as a single ErsatzTV item
Opened
#616 MCP/API paging traps: pageNum documented 1-based but is 0-based, pageSize cap doesn't clamp the offset, and playout rows carry no channelId
Opened
#617 .claude/skills/jellyfin/ is a stale divergent copy, not the symlink CLAUDE.md describes — it documents auth that v12 only accepts by legacy opt-in
Opened
#620 decisions corpus consolidation has no owner — and after #610 the budget number stops reporting it
Opened
#621 decisions: a record file that fails to parse is silently invisible — no structural "one keyed record per file" check
Opened
#622 merge gate: docs-only exemption is computed from a TRUNCATED file list (confirmed); auto-merge scheduling also freezes H10 consent (structural)
Opened
#627 Re-arm the MySQL data-migration fixture in CI — the dedupe DML has no automated coverage on MySQL
Opened
#629 merge gate: false-opens in the H10 verdict classifier — an undefined token, code blocks (fenced/indented/HTML), a URL-borne sha, and a read path that failed open
Opened
#631 scripts/tests/ is never executed by CI — the Python test suite is local-only
Opened
#632 A PR base change leaves the head sha — and so the review-verdict/h10 status — unchanged
Opened
#633 OpenAPI pageNum parameters carry no description, so the 0-based contract is invisible to REST consumers
Opened
#634 Rerun-collection picker in SchedulesScreen silently truncates at 100 (asks for pageSize 1000, server clamps to 100)
Opened
#640 ~25 music-video files are on disk but never ingested by Jellyfin — 4 folders short of their file count (not multi-version merging)
Opened
#643 Merge-consent gate fails OPEN on jq 1.6: a transport failure mid-pagination lets the docs-only exemption fire over a PARTIAL file list
Opened
#644 Seven more SPA list loads silently truncate at the server cap (same class as #634, one screen over)
Opened
#647 H10 verdict classifier is inert on jq 1.6: contains("�") matches every string, and a parse error is indistinguishable from an empty list
Opened
#648 Pin or preflight jq in CI: the runner ships 1.6, dev machines ship 1.8.x, and that gap silently broke three shell gates
Opened
#649 The ENFORCED review-verdict.yml guard is weaker than the advisory local hook — duplicated security logic has drifted
Opened
#650 Two more list loads truncate at the cap — but at-cap, so #644's over-cap grep could not see them
Opened
#651 Library-browse pickers need a searchable source, not a 100-row window or a full-library crawl
Opened
#652 Revive the generated-initials logo bug by caching it, not by fetching it at render time
Opened
#653 Song-progress overlay bypasses WatermarkSelector and can hand ffmpeg a nonexistent -i path
Opened
#660 Anamorphic HDR sources are excluded from the QSV OpenCL tonemap (runtime sar vs calculated SAR)
Opened
#661 HardwareUploadVaapiFilter(setFormat, deriveDevice = false) — a defaulted bool that silently strands frames on the wrong device
Opened
#662 Typeahead artist suggestions miss free-text credits; album_artist 404s — value-converted list columns have no suggestion source
Opened
#663 A review-verdict/h10 success is repo-global, so a second PR with the same head inherits it
Opened
#664 pr-changed-files.sh head binding cannot see an A→B→A force-push across its paging round-trips
Opened
#665 ChannelBuilder library-browse "Load more": cross-page sort order and an overclaimed totalCount permit no-op requests
Opened
#668 Facet-value typeahead misses accented values on the EF-sourced fields (LOWER() is ASCII-only on SQLite)
Opened
#669 Song artist typeahead scans the whole SongMetadata table per keystroke — consider a normalized SongArtist join table
Opened
#670 FillerPresets: collection-family selections outside the first 100 browse rows render as #150 instead of a name
Opened
#671 Rerun collections: the list endpoint returns a null selection for every row, and the detail GET 500s or nulls for five media types
Opened
#672 review-verdict.yml is head-resolved, so a PR editing it can self-approve the required check
Opened
#674 decisions_validate.py stays green on frontmatter PyYAML rejects — an apostrophe in a single-quoted scalar (hit twice in one session)
Opened
#677 Selection-id boundary: ScheduleItemInspector is unguarded, and list-backed pickers drop malformed options silently
Opened
#684 main is red: the #650 pageSize call-site guard keys its registry on line:column, so any merge that shifts a line breaks it
Opened
#685 CollectionsScreen AddItemsDialog windows the whole media-library type on an empty query, with no truncation surfaced (§3b deviation)
Opened
#688 decisions_validate ceiling calibration test is one line from red — any record ≥61 prose lines fails script-tests
Opened
#689 LibraryFolderDedupeMigrationTests claims CI sets ETV_REQUIRE_MYSQL_TESTS=1 — nothing does
Opened
#690 Rerun collections: paged list TotalCount ignores the search query, so the SPA renders empty pages
Opened
#691 SongVideoGenerator dereferences the nullable SongMetadata.Artists unguarded — NRE on the playback path
Opened
#697 ETV_STATUS_AUTH can write commit statuses, so any head-resolved workflow can still forge review-verdict/h10
Opened
#698 The review-verdict/h10 exemption path decides from mutable PR state — three routes to a forged exemption
Opened
#701 Search indexers mutate SongMetadata.Artists on a possibly-tracked entity (??= []) — same shape rejected in #691
Opened
#706 review-verdict/h10 writes are not serialized — a stale run can overwrite a fresher verdict (ABA retarget + human-rejection race)
Opened
#707 pr-changed-files.sh paging can drop a path when the base branch advances mid-enumeration
Opened
#708 Reproduce #698 route 2 live: push code onto a renovate-authored PR branch and confirm the manifest allow-list refuses the exemption
Opened
#711 .codex/ mirrors the gate-enforcing hooks but is absent from the merge gate's PROTECTED list
Opened
#713 chore: ignore .codex/ and stop shipping a plaintext Gitea credential in tracked docs
Opened
#715 chore(deps): land the three stalled Renovate patch bumps as one batch (#679, #680, #681)
Opened
#719 H11 pre-push guard blocks a tag-only push, on every release cut
Opened
#720 docs(ci-cd): a Komodo stack named ersatztv now exists on jazz — and it is NOT prod
Opened
#721 Auto-Tune proposal rows should be a grid — channel numbers do not line up, and the name renders twice
Opened
#726 Embedded BITMAP subtitle (PGS/DVD) burn-in + -readrate halves transcode to 0.53x realtime — Live TV buffering
Opened
#727 FFmpeg version health check warns on our own bundled FFmpeg — hardcoded 7.1.1 vs bundled 8.1.2
Opened
#728 Channels list: row checkbox renders a visible "Select <channel name>" label, duplicating the name column
Opened
#729 Channel edit → Branding: logo renders broken — detail endpoint returns a relative logo path, list endpoint returns absolute
Opened
#730 Settings → System: stale "managed in the legacy UI" copy pointing at a UI removed in #91b, and it renders as a dead link
Opened
#731 Dashboard "On air now": channel logo never rendered — ChannelLogo is called without src, always falling back to initials
Opened
#732 On Now / Next overlay: give it a boxed background for legibility, and enable it on all channels by default
Opened
#733 dvbsub/dvb_subtitle are missing from both IsImage lists, so DVB bitmap subtitles are routed down the text/libass path
Opened
#734 SPA: field-level progressive disclosure — short summary → hover popup → (future) deep-dive docs link
Opened
#735 Validate FFmpeg profile numeric fields to sane ranges instead of silently transforming them, and expose readrate pacing as a bounded field
Opened
#736 Advanced: editable FFmpeg arguments box — show the composed command, allow override, reset to default
Opened
#740 AddItemsDialog.runSearch has no stale-response or is-mounted guard (pre-existing, surfaced during #685)
Opened
#742 Tighten review-verdict.yml provenance from "non-null creator" to an allow-list of approved reviewers
Opened
#743 review-verdict/h10 is bypassable without forging it: direct pushes to main are server-side permitted
Opened
#744 ci-image.yml's push trigger has no branches: filter — any branch push runs attacker YAML on a docker-capable runner
Opened
#746 docker-build.yml checkouts should set persist-credentials: false — after the || true fetch masking is removed
Opened
#747 Re-verify the Gitea 1.25.4-pinned CI claims after the 1.27.1 upgrade
Opened
#748 Declare permissions: on the status-writing workflows so the Gitea Restricted token default can be enabled
Opened
#751 review-verdict.yml's classify/post step never executes — job goes green, review-verdict/h10 is never posted automatically
Opened
#754 MCP ersatztv_update_channel omits graphicsElementIds — cannot set the On Now/Next overlay, and silently strips it
Opened
#755 Project boundary: ersatztv owns the fork code, media-management owns channel operations
Opened
#756 Extend the dropped-step guard to docker-build.yml's required jobs, where a dropped step is fail-OPEN
Opened
#757 MCP tool catalog: query parameters are unguarded — list_playouts omits query, get_playout_items omits showFiller
Opened
#758 GetPagedPlayouts: TotalCount ignores the query filter, so a filtered page reports the unfiltered total
Opened
#759 MCP query-parameter guard ignores a $ref'd OpenAPI parameter instead of failing loudly
Opened
#763 Page both /statuses/{sha} reads in review-verdict.yml — limit clamps to 50, so the post-write race check can miss a raced verdict
Opened
#767 Make the delimiter ban fail-CLOSED on the release path — build's Smoke step is still droppable on a v* tag push
Opened
#772 The pinned CI toolchain image can vanish from the registry and take ALL container CI down, with no signal but a pull error
Opened
#773 Root-cause the recurring defect shapes across closed issues, then build hooks/tooling that make them hard to repeat — plus an audit of the tooling we already have and don't use
Opened
#774 Guard convention: derive the expected set from the authoritative source and assert equality — never filter, never sample
Opened
#775 Every guard ships with a proof it can go red: delete that guard alone, the suite must fail
Opened
#776 Make hooks report that they fired — PreToolUse/PostToolUse execution is currently unobservable
Opened
#777 csharp-lsp and typescript-lsp are broken; the "workflow agents must use csharp-lsp" guidance is stale
Opened
#778 Audit read-then-write against live remote state: pin a version or use compare-and-set
Opened
#779 Test the deny path with the production config value, and assert full-replace field lists
Opened
#780 Reconcile Python tooling: commit a ruff config and enforce it, or stop claiming we enforce it
Opened
#781 Plugin/MCP config hygiene: retire what is enabled and never invoked, de-duplicate the gitea server
Opened
#783 ersatztv skill states the stack names correctly but does not warn that two of the three fail silently
Opened
#784 Generalize the no-session-narrative rule from the kickoff file to all docs — the reader never saw the earlier draft
Opened
#785 Mutation proofs for the 19 unproven guards, worst-consequence first
Opened
#786 Extend the machine-checked guard inventory to inline workflow-job guards
Opened
#787 The dropped-step guard's SCOPE is a dated comment, not a check, against branch protection
Opened
#788 One shared verdict vocabulary instead of two shell copies plus a parity test
Opened
#789 Derive the CI toolchain population from workflow-owned metadata, not TOOLCHAIN_JOBS
Opened
#790 An executable clause-level mutation harness for the shell and python guards
Opened
#792 post-review-verdict.sh exits 0 when it deliberately writes NO status
Opened
#794 A fix ships a test witnessed failing BEFORE the fix — mechanise it by reverting the code side and asserting red
Opened
#796 A verification harness is itself unproven code — five false greens, each created by the fix for the last
Opened
#797 pretooluse-bom-guard.sh is fail-open wherever xxd is not installed — including the CI runner
Opened
#799 serena is enabled and starts fine, but its tools never reach a session — establish why, then use or disable it
Opened
#803 Head-ABA: a force-push H1->H2->H1 during paging defeats pr-changed-files.sh, and three contracts still deny it
Opened
#806 Guard populations over FILES should derive from the git index, not a filesystem walk
Opened
#807 The SPA's hand-built request objects can silently drop an OPTIONAL DTO field
Opened
#809 The production-hook-fire-log isolation guard is per-test, but its claim is per-suite
Opened
#812 Remediate the 21 session-narrative sites #784's sweep found — 21 judgements, not a regex
Opened
#816 Mutation harness: reset_sandbox does not restore .git control state
Opened
#819 The SPA page-size guard enumerates web/src with a Vite glob while claiming completeness
Opened
#820 Complete<T> proves its semantics but not its APPLICATION — nothing derives the set of SPA full-replace construction sites
Opened
#821 curl -u "$VAR" puts a credential in argv on shared hosts — five call sites, one class
Opened
#822 test_the_suite_does_not_write_to_the_PRODUCTION_log uses global mutable state as its oracle — any concurrent session reddens it
Opened
#823 Scheduling collection-valued columns: is a runtime null reachable on DaysOfMonth / MonthsOfYear / DaysOfWeek?
Opened
#824 ElasticSearchIndex.UpdateSong has no regression test — an Elastic-only reintroduction of the #701 mutation stays CI-green
Opened
#830 AddItemsDialog: a failed add is silently swallowed when the dialog is closed mid-request
Opened
#832 MediaCards paged handlers: 1-based paging + delete-or-keep (count drift fixed in #690/#758)
Opened
#835 Guard the persist-credentials convention — after #744, with no exemption list
Opened
#836 :latest images ship InformationalVersion 0.0.0 — a --depth=2 fetch grafts the build job's full clone shallow
Opened
#837 Scripted-playout _off: the documented "null -> all off" behaviour depends on an unrecorded formatter setting, and no test would catch it changing
Opened
#839 FieldHelp's panel placement is verified by hand, not by a test
Opened
#840 FieldHelp's portalled panel puts a docsHref link at the end of the tab order
Opened
#844 Per-channel default-adoption state, so "on by default" can stop re-adding an overlay the operator cleared
Opened
#845 post-review-verdict.sh does not check that its own account is on the gate's H10_REVIEWERS allow-list
Opened
#848 The QSV frame-pool 422 can name a control the editor is not rendering
Opened
#849 review-verdict.yml post-write verification: three routes that leave an exemption success over a human failure
Opened
#853 workflow_dispatch still loads attacker YAML from an arbitrary ref — four workflows, no ref restriction
Opened
#854 docker/ci/Dockerfile's FFMPEG-bump comment still says a push publishes — and cannot be fixed on its own
Opened
#855 Nothing couples ci-image.yml's push.paths to ci-image-pin's expected pathspec
Opened
#858 pretooluse-merge-consent.sh resolves its verdict classifier from $CLAUDE_PROJECT_DIR — an env var as a security input
Opened
#859 Merge-gate branch-protection read: a malformed rule states a cause that did not happen, and the endpoint is now fetched twice
Opened
#869 Finish the 1.25.4-dated CI claim sweep #747 deliberately did not complete
Opened
#870 The timeline walk's null terminator is defeatable: Gitea pages BEFORE it filters, so a page of inline-code comments reads as exhaustion
Opened
#876 docs.no-session-narrative reaches hooks and code comments, but nothing has ever swept them — 4 known sites
Opened
#877 Dismissible write failures, shape A2: the error state survives but its render site is gated by the same condition dismissal clears
Opened
#880 Schedule-item recurrence fields: an omitted array means "never applies" on write but "unrestricted" on read
Opened
#881 Mutation claims in PROSE are outside testing.mutation-claims-are-executed — 4 false ones in #812, each caught by a separate review round
Opened
#885 Same-repo pull_request runs get REGISTRY_PASSWORD from head-supplied YAML — the route #853 found under the dispatch class
Opened
#886 release.verdict-vocabulary-shared explains the sentinel with a set -u mechanism that measurement refutes
Opened
#887 Every image build fails: completeAnnotations.guard.test.ts needs the git index, and the Dockerfile's exclude list is hand-maintained
Opened
#891 ETV_HOOK_FIRE_LIB is SOURCED from an env-var path in 12 hooks — a decoy tree's code runs inside the gate
Opened
#893 page_statuses still terminates on its first empty page — is /statuses/{sha} subject to #870's post-pagination filtering?
Opened
#894 SPA lets a user build an empty recurrence set the server now rejects (#880 residual)
Opened
#895 "all N tests stayed green" claims in test comments go stale the moment anyone adds a test — 4 found, no detector
Opened
#900 chore(release): cut and promote v26.15.0 on 736649b3b (main head could not build an image)
Opened
#901 Convention: for a predicate over shell or config TEXT, pin the artifact whole — "match a shape" is the exception that must argue for itself
Opened
#904 test_docs_only_detector_clone_depth.py flakes ~8% in the CI container (measured, pre-existing on main)