Commit Graph
2919 Commits
Author SHA1 Message Date
timothyandClaude Opus 4.8 88287bcdb3 docs(queue): Gitea milestone-name issue filter silently no-ops on ':'/'+' names
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m15s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 6m26s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 6m2s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m34s
The `?milestones=<name>` filter returns the whole open-issue list (not a
filtered set) when the milestone title contains special chars, mis-tiering
issues during queue selection. Recipe: fetch open issues once, filter locally
on `.milestone.title`. Also notes the dependencies-API owner/repo/index form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 01:17:15 +02:00
timothy a5ac63dbd9 Merge pull request 'feat(69): Auto-Tune SPA wizard (Configure → Preview → Create) — PR2' (#389) from feat/69-auto-tune-spa into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 4m13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m51s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 7m38s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m47s
2026-07-16 22:30:52 +00:00
timothyandClaude Opus 4.8 9741ce7d6a docs(queue): dependency-aware selection + milestones-as-bundles grooming conventions
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Backlog grooming (2026-07-17): the kickoff cascade now excludes any issue with an
open blocked-by dependency (Gitea GET /issues/{n}/dependencies; auto-clears when the
blocker closes) so a blocked issue is never picked ahead of its blocker. Adds the
parked->closed convention and the bundle model: related work is grouped via active-arc
milestones or cross-reference comments and detected on pickup via milestone + backlinks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 00:27:42 +02:00
timothy 7ef7ef25e8 Merge pull request 'feat(71): per-playout reshuffle + shuffle-state surfacing' (#387) from feat/71-reshuffle-playout into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been cancelled
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Merge pull request '#387' (feat(71): per-playout reshuffle + shuffle-state surfacing) from feat/71-reshuffle-playout into main

fixes #71
2026-07-16 22:19:03 +00:00
timothyandClaude Opus 4.8 8e82673e6b fix(69): key Auto-Tune selection by axis+value; zero-templates UX (review)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 5m43s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 9s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 8s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m3s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 12m10s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Addresses the cold-review findings on PR #389:
- Medium: selection was keyed by proposal name, coupling two same-named
  proposals (e.g. a show titled "Comedy" and the "Comedy" genre) so toggling
  one flipped both. Now keyed by axis+value (unique); adds a regression test.
- Low: zero channel templates now shows a hint on Configure and the Create
  tooltip explains the missing template instead of a misleading positive label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 00:16:03 +02:00
timothyandClaude Opus 4.8 33ba3a0492 feat(69): Auto-Tune SPA wizard — Configure → Preview → Create (PR2)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 9s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m52s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 12s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 8s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 8m37s
New `/app/auto-tune` screen driving the PR1 endpoints: pick metadata axes
(TV Shows / TV Genres / Movie Genres) + defaults, preview proposed channels
grouped by axis with per-row/per-group selection and already-exists dedup,
then bulk-create with a Created/Skipped/Failed summary. Additive/non-destructive.

The per-channel DetailPanel from the design iteration is deferred to #383
(new endpoints backlogged) — this ships the 3-step wizard only.

- web/src/api/autoTune.ts (+test), web/src/screens/AutoTuneScreen.tsx (+test)
- route/nav (routes.tsx, ScreenContent.tsx), api barrel, App nav-smoke test
- docs: domain-model (route), blazor-route-parity (net-new SPA screen)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 00:04:42 +02:00
timothy 181eabdded Merge pull request 'test(163): golden characterization tests for playout building (Classic + Block)' (#382) from feat/163-playout-goldens into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 5m40s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 3m55s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 10m3s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
2026-07-16 22:01:33 +00:00
timothyandClaude Opus 4.8 1131ecacfb test(163): apply review nits — instant-accurate Block TZ guard + determinism notes
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 10s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m9s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 9s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 40s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m11s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 7m33s
Follow-up to the cold adversarial review of PR #382 (MERGEABLE-WITH-NITS):
- Block TZ guard: BaseUtcOffset -> GetUtcOffset(Start). BaseUtcOffset is zero
  year-round for DST zones like Europe/London, so it would pass in a summer-dated
  fixture where London != UTC; GetUtcOffset pins the actual build instant and is
  correct regardless of fixture date. (Safe today — mid-Jan fixture — but removes
  the latent fixture-date dependency the reviewer flagged.)
- Document the determinism invariants the fixture relies on: golden captures raw
  builder output (pre-trim AddedItems), Classic is TZ-independent for the captured
  fields (no guard needed), and ResetPlayout's random Seed can't perturb the
  Chronological fixture (RandomStartPoint/ShuffleScheduleItems false, distinct
  release dates).

Re-verified: TZ=UTC both goldens pass; TZ=America/New_York Block skips, Classic
passes; no golden drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:47:54 +02:00
timothyandClaude Opus 4.8 81684411bd fix(71): reseed all playout kinds on reshuffle (erase-history + rebuild); docs + minors
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 4m54s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m24s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 6m58s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 11m14s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 16m11s
Reset only reseeds Playout.Seed for Classic playouts (PlayoutBuilder); Block/
Sequential/Scripted rebuild deterministically from the existing seed, so
reshuffle was a silent no-op for 3 of the 4 supported kinds (C1). Fix:
ReshufflePlayoutHandler now sends ErasePlayoutHistory (reseed + clear anchors/
history, the only primitive that reseeds all four kinds) before enqueueing
BuildPlayout(Reset).

Also: correct docs/decisions.md's false "Reset already reseeds..." claim,
fix the SPA reshuffle test mock to return 202 (matches the real endpoint),
and gate the seed-help text to the resettable kinds (was showing even for
ExternalJson/None where no Reshuffle button exists).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:47:18 +02:00
timothyandClaude Opus 4.8 11d3ba3823 design(69): sync Auto-Tune prototype + handoff (incl. deferred DetailPanel → #383)
Iterated Auto-Tune prototype pulled back from the Claude Design working copy
(project 4eb64b16) into design-system/. The 3-step wizard (Configure → Preview
→ Create) is PR2; the per-channel DetailPanel it also contains is deferred to
the #383 arc (#384/#385/#386) per design-first — new endpoints backlogged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:46:46 +02:00
timothyandClaude Opus 4.8 dc5d889ccb test(163): golden characterization tests for playout building (Classic + Block)
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 9s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 10s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 12s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 44s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m56s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m41s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 11m33s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Add ErsatzTV.Core.Tests/Scheduling/Goldens/PlayoutBuildGoldenTests.cs — a
golden-file net that snapshots the PlayoutItems each builder produces over a
pinned build window; the scheduling counterpart to the M3U (#11) / XMLTV (#28)
goldens. This is the regression net that de-risks the scheduling-refactor
chain (#380 -> #70/#71/#176).

Coverage this slice:
- Classic (PlaybackOrder.Chronological)
- Block (TimeZoneInfo.Local-guarded to UTC via Assume: runs in CI, skips
  gracefully under a non-UTC TZ; a real TZ seam is #380's scope)

Determinism: the builders read no wall clock (time enters only via the
caller-supplied start), so a pinned start is fully deterministic. Snapshots the
raw UTC Start/Finish, not the *Offset properties (which .ToLocalTime()). Regen
via ETV_UPDATE_PLAYOUT_GOLDENS (deliberately separate from ETV_UPDATE_GOLDENS).
Both goldens proven non-vacuous.

Sequential (YAML) + Scripted goldens tracked as a follow-up in #381.
Docs: docs/testing.md updated (third golden net + env var + Block TZ guard).

fixes #163

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:41:33 +02:00
timothyandClaude Opus 4.8 6a4d81f862 docs(71): reshuffle action + seed surfacing (parity, domain-model, decisions)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:28:04 +02:00
timothyandClaude Opus 4.8 13584f5daf feat(71): SPA display play-order seed + persistence help text
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:25:33 +02:00
timothyandClaude Opus 4.8 7a01ad62bd feat(71): SPA per-playout Reshuffle button + client fn
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:22:33 +02:00
timothyandClaude Opus 4.8 238937fa5b chore(71): regenerate OpenAPI + client for reshuffle endpoint + seed field
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:19:46 +02:00
timothyandClaude Opus 4.8 e7072e49a8 feat(71): surface Playout.Seed on playout list + detail DTOs
Task 3 of ersatztv#71 (reshuffle-playout). Appends Seed as the last
positional field on PlayoutNameViewModel, threading it through the
Mapper list projection, GetPlayoutByIdHandler detail projection, and
the four Update*PlayoutHandler VM constructions, then exposing it on
PlayoutListItemResponseModel/PlayoutResponseModel via the controller's
ToResponse/ToListItemResponse mappers.

ChannelControllerTests.MakePlayout was an additional construction site
not listed in the task brief (positional-record break); updated to
append 0 for Seed alongside the brief's ErsatzTV.Tests changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:15:52 +02:00
timothyandClaude Opus 4.8 a9d9fc8afb feat(71): POST /api/v1/playouts/{id}/reshuffle action (202/404/409/422)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:08:48 +02:00
timothyandClaude Opus 4.8 89c7d08cde feat(71): ReshufflePlayout command + handler (enqueue per-playout Reset build)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:04:43 +02:00
timothyandClaude Opus 4.8 1f4341a347 docs(71): implementation plan for per-playout reshuffle + seed surfacing
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:54:37 +02:00
timothyandClaude Opus 4.8 9a7ac28f9f docs(71): design spec for per-playout reshuffle + shuffle-state surfacing
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:43:29 +02:00
timothy 331a427040 Merge pull request 'feat(69): auto-tuning backend — enumerate library metadata, preview + bulk-create channels (PR1)' (#379) from feat/69-auto-tuning into main
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Failing after 13s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 5m7s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 8m44s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been skipped
2026-07-16 20:35:10 +00:00
timothyandClaude Opus 4.8 630d78a804 docs(queue): note maintenance/backlog phase so sessions stop re-discovering arc completion
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
The go-live arc (#237) is closed; add a 'Current phase' section stating the
terminal transition to backlog mode + structural guidance (empty arc/gate/review
tiers are the expected steady state; fall through to the priority-label cascade).
Drift-proof: terminal fact + structure only, no named frontier issue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:25:26 +02:00
timothy 938e4e0f50 chore(69): regenerate endpoint-index after rebase on origin/main
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 9s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m12s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m34s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m8s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 5m21s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 8m7s
Union of #340 IPTV-settings endpoints + auto-tune endpoints.

Refs #69
2026-07-16 22:20:53 +02:00
timothy dbd4bb43f7 Merge pull request 'feat(analyzers): enable incremental latest-All enforcement' (#375) from feat/15-analyzer-promotion into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m51s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 6m15s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 7m9s
v26.9.0
2026-07-16 20:19:07 +00:00
timothy 39b07e178d fix(channels): swallow rollback delete exceptions in auto-tune handler
DeleteSmartCollection rollback in CreateAutoTunedChannelsHandler.CreateOne
was called without exception handling; a transient infra exception during
the best-effort rollback would propagate and abort the whole batch,
contradicting the comment's stated intent. Wrap the send in try/catch so
an orphaned SmartCollection is the accepted degraded outcome instead.
2026-07-16 22:18:52 +02:00
timothy f31476e012 fix(69): auto-tune review fixes — null channels, orphaned SmartCollection, oversized preview names, doc drift
- CreateAutoTunedChannelsRequest.ToCommand(): guard null Channels (was NREing on
  a request body that omits "channels", causing HTTP 500).
- CreateAutoTunedChannelsHandler.CreateOne: when CreateChannelFromLineup returns
  Left (Skipped/Failed), roll back the just-created SmartCollection via
  DeleteSmartCollection so retries don't fail on SmartCollection-name uniqueness.
  Best-effort; the delete result does not change the outcome.
- PreviewAutoTuneChannelsHandler: filter out proposals whose generated name
  exceeds the 50-char Channel.Name limit before number allocation, so numbers
  aren't wasted on proposals that can never be created.
- docs/superpowers/specs/2026-07-16-auto-tuning-design.md: fix field-name drift
  in JSON examples (proposedNumber -> number, error -> reason) to match the
  actual AutoTuneProposal/AutoTuneChannelOutcome DTOs.

Refs #69
2026-07-16 22:18:52 +02:00
timothy 0320735f47 docs(69): auto-tune OpenAPI regen + api/domain/decisions docs
Refs #69
2026-07-16 22:18:52 +02:00
timothyandClaude Opus 4.8 a2c056dd7a docs(release): prepare v26.9.0 promotion [decisions-edit]
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Consolidate docs/decisions.md (1923 -> 1028) by extracting four cohesive
topic clusters into docs/decisions/ (optimistic-concurrency,
api-auth-security, release-ci-governance, spa-modularization) — content
relocated verbatim (lossless; all rationale + reversals preserved), main
Index rebuilt to reference the topic files plus the remaining in-file
entries, docs/README.md points back at the decisions Index. Add the
v26.9.0 row to the ci-cd.md version table.

refs #340

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:17:23 +02:00
timothy e9e701f621 feat(69): auto-tune preview + bulk-create REST endpoints
Refs #69
2026-07-16 22:16:43 +02:00
timothy 4a7bd0b24c feat(69): auto-tune bulk-create orchestration handler
Refs #69
2026-07-16 22:16:43 +02:00
timothy 0d57cb6c0d feat(69): auto-tune preview query + EF enumeration handler
Refs #69
2026-07-16 22:16:43 +02:00
timothy 456c2c7c84 feat(69): auto-tune channel-number allocator
Refs #69
2026-07-16 22:16:43 +02:00
timothy 9605f9ea65 feat(69): auto-tune axis map (query/name/order/escape)
Refs #69
2026-07-16 22:16:43 +02:00
timothyandClaude Opus 4.8 2352604836 docs(69): PR1 backend implementation plan
Task-by-task TDD plan for the auto-tuning backend: axis map, number
allocator, preview query + EF enumeration, bulk-create orchestration,
REST endpoints, OpenAPI + docs.

Refs #69

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:16:43 +02:00
timothyandClaude Opus 4.8 35ad7df6a4 docs(69): auto-tuning 3-axis MVP design spec
Design for #69 auto-tuning: enumerate library metadata (TV Show / TV
Genre / Movie Genre) -> preview -> select -> bulk-create channels.
Additive/non-destructive, enumerate-via-EF + persist-via-SmartCollection,
server-side query generation, reserve-block numbering.

Refs #69

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:16:43 +02:00
timothy b17a70be1b Merge pull request 'fix(spa): body margin + nav box-sizing resets (#373, #377)' (#378) from fix/373-377-spa-css-resets into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m11s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
2026-07-16 20:12:52 +00:00
timothyandClaude Opus 4.8 1575b9b537 fix(spa): add body margin + nav box-sizing resets (fixes #373, fixes #377)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 10s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 16s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 16s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m41s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m18s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 6m4s
Two missing-base-reset defects in the ChicoryTV SPA shell, both confirmed by
rendering the real app (not source-reading):

- #373: the browser-default `body { margin: 8px }` was never reset, so it framed
  every full-viewport layout — the app shell and the shell-less `.ctv-auth-page`
  boot pages (login/setup/checking/error), both `min-height:100vh` — with a light
  border on all four edges. Fix: `html, body { margin: 0 }` + paint the app surface
  on `body` so any residual gap/overscroll stays dark (matches the design-system
  reset in forms.card.html / chicorytv-admin templates). Verified body margin 0 and
  no edge border on the boot page and the shell, warm theme, 1280px and 900px.

- #377: the SPA ships no global `box-sizing` reset (default content-box), so
  `.ctv-nav-item { width:100%; padding:0 10px }` overflowed `.ctv-nav`
  (`overflow:auto`) by 20px → a horizontal scrollbar in the sidebar. Fix: scope
  `box-sizing: border-box` to `.ctv-nav-item`. Verified nav scrollWidth==clientWidth
  (216==216) and no horizontal scroll after the fix; the intended vertical nav scroll
  is unaffected.

Docs: spa-conventions.md §1 records the base reset and the deliberate absence of a
global box-sizing reset (set border-box locally when combining width:100% + padding).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 21:57:29 +02:00
timothyandCodex 10ae885b47 fix(analyzers): preserve non-CPM and image builds
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 10s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 17s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 5m12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m52s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 2m40s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m40s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Guard analyzer package references for the inline-version MCP tool and copy the SDK suggestion baseline into the Docker build context before restore.

Refs #15

Co-Authored-By: Codex <codex@openai.com>
2026-07-16 21:52:27 +02:00
timothyandCodex 8f90cea5cc feat(analyzers): enable incremental latest-All enforcement
Centralize SDK and threading analyzers, baseline the .NET 10 All rule inventory at suggestion severity, and promote S3981 repo-wide. Fix the always-true worker count predicate and cover the idle/active branches.

Fixes #15

Co-Authored-By: Codex <codex@openai.com>
2026-07-16 21:52:27 +02:00
timothy 9938d9a6cd Merge pull request '#340: configurable advertised IPTV base URL for M3U/XMLTV' (#374)
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m3s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 3m34s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 9m0s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m44s
2026-07-16 19:51:27 +00:00
timothyandClaude Opus 4.8 dd273fbbb2 docs(202-e2e): record completed Plex real-server pin-flow validation
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m25s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 5m25s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Completes the outstanding Plex flow in the #202 post-merge integration
checklist against a disposable test Plex Media Server: pin-flow auth,
server/library discovery (the 2026-07-13 gap that returned servers:[]),
sync-preference persistence, and sign-out cleanup all passed. Records
exact API state evidence and the test-admin credential reset.

fixes #333

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 21:39:16 +02:00
timothyandClaude Opus 4.8 27d01db265 fix(iptv): XML-escape advertised base URL in XMLTV guide output (#340 review)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 10s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m37s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m30s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m10s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 4m21s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 9m43s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Independent review found that AdvertisedBaseUrl.TryParse accepts a path
prefix containing '&' (a legal URL-path char kept out of uri.Query), but
GetChannelGuideHandler substituted {RequestBase} raw into pre-built XML
written unescaped — so a configured base like https://host/a&b emitted a
bare '&', malforming the entire XMLTV guide (clients reject the document).

Escape the substituted base with SecurityElement.Escape before the raw
replace, mirroring how {AccessTokenUri} is already pre-escaped (&amp;).
No-op for normal URLs (goldens unchanged); M3U output is untouched (M3U
isn't XML). Adds a regression test asserting '&' → '&amp;' in the guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 21:08:42 +02:00
timothyandClaude Opus 4.8 3bc8192d3b feat(iptv): add configurable advertised base URL for M3U/XMLTV (fixes #340)
ErsatzTV built every absolute M3U/XMLTV URL from the incoming request's
Scheme/Host/PathBase, so a client fetching via a host that downstream
consumers can't resolve (e.g. Dispatcharr over Docker DNS → Kodi) baked
that internal host into programme-image/stream URLs.

Add an optional advertised IPTV base URL, backed by the existing
ConfigElement key/value store (key `iptv.base_url`, no EF migration):

- Central pure Core helper `AdvertisedBaseUrl` (TryParse/Resolve):
  validates absolute http(s), no credentials/query/fragment, preserves
  port + path prefix, normalizes trailing slash. Blank/invalid falls
  back to the request-derived values, so unset output is byte-identical.
- Resolved inside `GetChannelPlaylistHandler` (M3U guide/logo/stream) and
  `GetChannelGuideHandler` (both XMLTV {RequestBase} sites) — controllers
  stay thin, golden tests untouched.
- New `iptv` settings group: GET/PUT /api/v1/settings/iptv (blank clears,
  malformed → 422) + a new IPTV section on the SPA Settings screen.
- Scoped to M3U + XMLTV; HDHomeRun deliberately out of scope. Distinct
  from ETV_BASE_URL (which only sets ASP.NET PathBase).

Tests: AdvertisedBaseUrl unit tests (override/fallback/port/path/invalid),
handler override tests for both generators, settings controller + handler
tests, SPA client + screen tests. Docs: m3u-xmltv, decisions, domain-model,
regenerated OpenAPI v1.json + v1.d.ts + endpoint-index.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 21:08:42 +02:00
timothy de16a7c066 Merge pull request 'chore(deps): update dependency jetbrains.resharper.globaltools to 2025.3.4.1' (#329) from renovate/jetbrains.resharper.globaltools-2025.x into main
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 3m37s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m16s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 7m58s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m8s
2026-07-16 18:47:04 +00:00
timothy be85a462a4 Merge pull request 'chore(deps): update dependency humanizer.core to 3.0.10' (#328) from renovate/humanizer-monorepo into main
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m22s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 5m23s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
2026-07-16 18:38:12 +00:00
timothy 95d58f3b69 Merge branch 'main' into renovate/jetbrains.resharper.globaltools-2025.x
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 10s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 11s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 13s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 7s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m16s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m58s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 10m49s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
2026-07-16 18:35:14 +00:00
timothy 3654fad163 Merge pull request 'ci(coverage): collect code coverage and publish a summary (refs #15)' (#370) from feat/15-ci-coverage into main
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m21s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 5m40s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 6m21s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m44s
2026-07-16 17:29:34 +00:00
timothy 9f0bb65fb4 docs(queue): exclude parked selector candidates (#372)
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Failing after 1m43s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Refs #237
2026-07-16 17:25:10 +00:00
timothy 72d47ef052 fix(api): protect local library path details (#371)
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been cancelled
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been cancelled
Build ErsatzTV Image / Build & test (.NET) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Fixes #334
2026-07-16 17:16:51 +00:00
timothyandClaude Opus 4.8 e78aa01c05 ci(coverage): exclude generated EF migrations to stop coverage OOM (exit 137)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m26s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 16s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 17s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m5s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m46s
The shared Build & test job OOM-killed (exit 137) with coverage enabled: the
whole-solution Architecture.Tests process instruments both EF migration folders
(~2.59M generated lines vs ~200k authored), ballooning coverlet's in-memory
hit-count arrays past the runner's limit.

Add coverlet.runsettings excluding **/Migrations/*.cs (+ generated/compiler
attributes) and pass it via --settings on the Test step. This cuts the
instrumented surface ~126x (2,510,185 -> 19,963 coverable lines in the
Architecture.Tests process, verified locally) and makes the reported percentage
reflect authored code. Documented in docs/ci-cd.md.

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