b8ea62bfa0c72fcb15ab5cefeb6a1b253df45020
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fcdc381246 |
docs(568): the rule the branch establishes gets a record, and every row the fix moved is re-measured
Build ErsatzTV Image / CI toolchain image resolves (pull_request) Successful in 7s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 13s
PR Gates / Docs update reminder (pull_request) Successful in 13s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 20s
PR Gates / decisions lifecycle (pull_request) Successful in 18s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 12s
Review verdict / Set review-verdict status (pull_request_target) Successful in 26s
review-verdict/h10 Review-verdict: MERGEABLE @ fcdc381 (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m23s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m23s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 17m33s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m7s
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 7s
api-conventions.md now says which half of an id-list validator a sibling field may gate (existence, never the raw-count cap) and that a lost-race recovery re-asks the whole validator set rather than the fields whoever wrote the catch remembered. Those, with the bound and the field-named 422, are one convention with residuals, so they get a record -- api.top-level-id-list-validation -- and a task-signal row. The record states what #568 does NOT settle: three validators on two DTOs is a per-field constant, not the repo-wide rule #917 owns, and it says to expect #917 to replace the mechanism. graphics-elements.md: rows 35-44 re-measured against the whole ErsatzTV.Tests project on this tree, because the fix moved five of their red sets -- Validate is now also what the recovery path re-runs, so removing a validator from it reddens that handler's race test too. Rows 45-47 are new and measured the same way. The "redden more than one test" figure is recounted from the table (21 -> 24); the cross-fixture set is unchanged at five. The negative discriminator rows now carry a stated seeding rule: vary one half of the identity and hold the other at the seeded value. Varying both leaves the row rejected by the pre-#568 predicate as well, so a composite revert to it would pass every test at that site. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
3541683c99 |
docs(568): re-measure every mutation row the merged identity and the shared validator moved
Nine rows of the mutation table in docs/graphics-elements.md name a clause that this branch's last commit moved, merged or gave new callers, and a red set is a measurement of the tree it ships in. All were re-taken against the whole ErsatzTV.Tests project (2139 tests, 6 skipped) on the code as it now stands, and four new rows added for the clauses the fix introduced. What moved and why the numbers changed: - Row 10 was the seeded-path filter alone. `Kind` now lives inside `IsOnNowNext`, so dropping the lookup's `Where` drops both halves at once and reddens four tests, not three. - Row 18 was the seeder's SQL `Kind == Text` filter and is now the `kind` conjunct of the shared predicate, so it reddens the API site too — a second cross-fixture row. - Rows 35-37 pick up the count-cap tests, since the cap rides in the validator they disarm. Rows 33, 34, 38, 39 re-measured unchanged. - Row 40's mutation text follows the API call's new two-argument shape; it reddens the new wrong-kind test as well. - Rows 41-44 are the new clauses: the raw-count cap (one clause, three call sites, which is what its red set shows), the diagnostic-id truncation, and the two lost-race catches. The two self-counted figures above the table were recounted from the table itself rather than adjusted: twenty-one multi-test rows and five cross-fixture ones (13, 18, 22, 33, 41). The deco lost-race test is renamed so no two rows cite the same test name. api-conventions.md gains the three rules the fix establishes for any write path with a top-level FK id list — bound the raw list, name the field, translate a lost check-then-write race — in the handler-hardening checklist where they belong rather than as a #568 anecdote. Refs #568 Decisions-Edit: yes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
722f0057e8 |
docs(568): bound the "cannot fail" claim to the two rows that measure it
The sentence explaining why the wrong-kind-and-wrong-folder case is not shipped said "no single-clause mutation can let it through" — an unbounded quantifier over a population nothing here measures. What is actually established is narrower and is established: rows 10 and 18 are the two clauses of `GetBuiltInElementId`, each measured, and dropping either leaves the other rejecting such a row. The claim now says that, and names those rows as its evidence. Refs #568 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
7fa223a567 |
test(568): drop the different-kind case no single-clause mutation can redden, and measure the API-site clause
`Ignores_A_Same_Named_Element_Of_A_Different_Kind` seeded an Image row at `/templates/image/on-now-next.yml` and asserted the backfill ignores it. Under the bare-filename lookup that row was rejected by the `Kind == Text` filter alone, which is what its comment described. Under the full-path predicate the path rejects it first, so neither clause is load-bearing for it: dropping the `Kind` filter reddens only `A_Row_Of_Another_Kind_At_The_Seeded_Path_Does_Not_Suppress_The_Built_In_Row` (row 18) and dropping `IsOnNowNext` reddens only the three tests of row 10. The test survived both and its comment claimed a mechanism it no longer exercised. Its scenario is the conjunction of two already-pinned negatives and is strictly weaker than `Ignores_A_Same_Named_Same_Kind_Element_Outside_The_Seeded_Folder`, so it is retired rather than reshaped, and graphics-elements.md now says why the combination is deliberately not shipped — otherwise the next reader re-adds it. Row 40 records the API-side half of the discriminator, which had a measured red and no row. Measured whole-project on this tree, `dotnet test ErsatzTV.Tests/ErsatzTV.Tests.csproj`: baseline `Failed: 0, Passed: 2123, Skipped: 6, Total: 2129`; with `BuiltIn = GraphicsElementDefaults.IsOnNowNext(e.Path)` reverted to `Path.GetFileName(e.Path) == GraphicsElementDefaults.OnNowNextFileName`, `Failed: 1, Passed: 2122`, the sole red being `GetAllGraphicsElementsForApi_Should_Not_Mark_Same_Filename_Outside_Seeded_Folder_As_BuiltIn`. The table's two self-counts were recounted from the table after adding the row and both still hold: sixteen rows redden more than one test, three of those span two fixture classes (13, 22, 33). Refs #568 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
9f0f21ec52 |
docs(568): measure the five validator mutation claims the tests assert in prose
Five test comments asserted "reddens if <validator> alone is removed" with nothing binding the sentence to a measurement -- the shape testing.mutation-claims-are-executed refuses, and the shape whose CLAIMS half of the manifest cannot reach a .NET proof. The repo's record for those is the mutation table, so each claim got a row: all five mutated in turn against this tree with the whole ErsatzTV.Tests project re-run (the tuple-arity fix included, since a mutation that does not compile is not a result). 35 GraphicsElementIdsMustExist out of UpdateChannelHandler.Validate -> 2 red; 36/37 the deco graphics/watermark validators out of UpdateDecoHandler.Validate -> 1 red each; 38/39 the two Consumes* mode gates -> 1 red each. Sixteen rows now redden more than one test; three still span two fixture classes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
41fd1f64de |
docs(568): re-measure the rows the seeder's lookup call moved, and recount the table's own claims
The seeder now resolves the built-in row through GetBuiltInElementId, which puts that lookup on a second call path, so every row whose clause the new call can reach was re-run against this tree: 10 and 33 unchanged, 18 reinstated (the Kind == Text filter has a red now that a wrong-kind row at the seeded path can suppress the row the lookup needs), 21 unchanged, 22 gains a third red, and 34 is new (the existence check re-derived as SQL instead of asking the lookup). Two stale measurements went with it. The "known clauses with no red" bullet for the Kind filter quoted 2121 passed against a tree that produces 2123, having been taken before the branch's last two tests existed -- the whole bullet is gone now that the clause has a red. And the per-fixture-filter trap counted thirteen multi-test rows with two spanning two fixture classes, true on origin/main and false here since the branch added rows: fifteen and three, both recounted from the table, with a note that they are. Decisions-Edit: yes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
cb11116d4f |
docs(568): stable row ids in the mutation table, and the case-sensitivity sign-off the issue's wording invites
Two review findings, both about docs the branch already rewrote.
The mutation-coverage table in docs/graphics-elements.md ended up with two rows
numbered 24 -- the new IsOnNowNext row was inserted after 23 without checking
what followed -- while 18 was vacated when the Kind-filter row moved to the
"no red" list. The section's own prose cites rows by number ("the IsOnNowNext
clause (row 10)"), so a duplicate id makes a citation ambiguous. The new row
becomes 33, the next unused number, and the rule that made it 24 in the first
place is now written down: a row number is an identity, not a position, so a new
row takes the next unused number, nothing is renumbered, and a retired clause
leaves its number vacant rather than having it reused under a new meaning. Both
row claims were re-measured and are unchanged; only the id moves.
#568's second half is titled "builtIn discriminator is filename-only,
case-sensitive, folder-agnostic", and the branch removes the first and third
while deliberately keeping case sensitivity -- which reads like two thirds of a
done-when box. It is not: the remedy the same box prescribes, "full seeded
relative path", is exactly as case-sensitive as the filename match it replaces,
so the three adjectives describe one predicate rather than name three separable
demands. Read the other way the box would be unsatisfiable by its own remedy.
The reason case sensitivity is kept -- a case-INsensitive test hands the built-in
identity to a user element differing from the seeded path only in case -- lived
only in GraphicsElementDefaults.cs, where a reader arriving from the issue title
would not find it. It is now in the active record that owns the discriminator.
Refs #568
Decisions-Edit: yes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV
|
||
|
|
ae314aa5ea |
docs(568): re-measure the built-in lookup's mutation rows against the code as it now stands
The mutation-coverage table's claims were measured against an earlier shape of GetBuiltInElementId and are re-taken here, because the lookup changed twice on this branch (filename -> seeded path, then SQL -> in-memory IsOnNowNext) and a claim about which tests a mutation reddens does not survive either move on its own. Measured 2026-09-05, each mutation applied alone to the committed tree: - Row 10, the seeded-path filter removed: 3 red, not the 2 the row listed. Ignores_A_Case_Variant_Of_The_Seeded_Path joins the two already named, because without the filter every Text row resolves as the built-in one. - Row 24 is new: IsOnNowNext loosened from Ordinal to OrdinalIgnoreCase reddens exactly the two case-variant tests, 2 failed / 77 passed. One row covers both discriminator sites because they now share the predicate. - The Kind==Text filter's "no red" bullet is re-measured across the WHOLE ErsatzTV.Tests project -- 2121 passed, 6 skipped, 0 failed -- rather than the 11 tests of the one file that names GetBuiltInElementId. ChannelGraphicsDefaults reaches the lookup from the channel-create handlers as well, so the narrower population could not have seen a red there. The conclusion is unchanged; what changes is that it is now measured over the population that could falsify it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
131c63f7f4 |
fix(568): one ordinal identity predicate for the built-in element, applied in memory at both sites
The branch moved the `builtIn` discriminator from a bare filename to the full seeded path, but split how the two sites evaluate it: the API handler compares in memory (ordinal) while GetBuiltInElementId's new `.Where(e => e.Path == OnNowNextSeededPath)` compares in SQL. GraphicsElement.Path takes no explicit collation -- TvContext.OnModelCreating pins one only on the listed name/title columns -- so SQLite answers that case-sensitively and MySQL uses the server default, which is normally case-INsensitive. On MySQL the two discriminators could therefore disagree about the same row: AttachOnNowNextByDefault would resolve a case-variant user element as the built-in one while the API reported builtIn:false for it. Collapse both onto GraphicsElementDefaults.IsOnNowNext, ordinal, applied in memory. GetBuiltInElementId goes back to loading the Text candidates and filtering in memory (the shape it had before this branch), keeping only the `Kind` enum filter in SQL. The prose claimed more than the code did. "A filename-only comparison is case-sensitive-by-accident" appeared in four places as a defect the full-path fix removed; a full-path comparison is exactly as case-sensitive, so the clause said nothing and implied a fix that had not happened. Case sensitivity is now deliberate and stated as such -- the built-in element is the exact file the seeder wrote, at the exact path it wrote it to -- and the reason the comparison is kept out of SQL is recorded where the predicate lives. docs/decisions/records/graphics/channel-level-attachment.md said BuiltIn was "computed by comparing the row's `Path` to GraphicsElementDefaults. OnNowNextFileName", which was true of neither the pre-#568 rule (filename to filename) nor the current one; an active record resolved by key now states the current predicate in its own sentence rather than in a parenthetical. Two tests pin the ordinal rule against a loosening to OrdinalIgnoreCase, one per site. Measured: OrdinalIgnoreCase reddens exactly GetAllGraphicsElementsForApi_Should_Not_Mark_A_Case_Variant_Of_The_Seeded_Path_As_BuiltIn and Ignores_A_Case_Variant_Of_The_Seeded_Path, 2 failed / 77 passed of the 79 graphics tests. They do NOT pin provider independence -- under SQLite's BINARY collation an equivalent SQL comparison answers identically, so no test in this suite can distinguish the two. That is stated at each site rather than left for a reader to assume the tests cover it. Decisions-Edit: yes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
352305ade8 |
fix(568): sync docs/comments to the seeded-path builtIn discriminator, harden UpdateDecoHandler's twin FK ids
Review round on #568 found the branch changed builtIn identity from a bare filename comparison to the full seeded path (GraphicsElementDefaults. OnNowNextSeededPath) but left several places still asserting the old rule: - docs/decisions/records/graphics/channel-level-attachment.md and on-now-next-on-by-default.md (both status: active) still described a filename-only match; corrected in place and cross-referenced. - docs/api-conventions.md §8 quoted the retired `Path.GetFileName(element.Path) == OnNowNextFileName` expression verbatim; replaced with the current OnNowNextSeededPath comparison and a note on the UpdateChannelHandler 422 hardening. - Three in-code comments (GraphicsElementDefaults.cs, GraphicsElementSeeder.cs, ChannelGraphicsDefaults.cs) still said "identity is the filename". - docs/graphics-elements.md's mutation-coverage table (row 10, row 18) named clauses that no longer exist or no longer redden any test post-#568; re-measured directly (removing the seeded-path check reddens Ignores_A_Non_Built_In_Element_With_A_Different_Filename and Ignores_A_Same_Named_Same_Kind_Element_Outside_The_Seeded_Folder; removing the Kind==Text filter alone reddens nothing, so it moves to the "known clauses with no red" list with that measurement dated). Also closed the should-fix twin: UpdateDecoHandler's graphicsElementIds and watermarkIds are top-level ReplaceDecoRequest fields in the same position as UpdateChannelRequest.graphicsElementIds (not the deep-FK-in-a-nested-list carve-out), and the reconcile in ApplyUpdateRequest blindly Added a join row for any incoming id -- the identical FK-constraint-to-500 defect #568 fixed on the channel path. Added GraphicsElementIdsMustExist/WatermarkIdsMustExist validators mirroring UpdateChannelHandler's, pinned by UpdateDecoGraphicsElementsTests (reddens when either validator alone is removed -- verified). Decisions-Edit: yes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
c84bdd2427 |
docs(568): record the full-seeded-path builtIn discriminator in graphics-elements.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
ba6a4b08aa |
feat(732): On Now / Next gets a background box, and is on by default (#843)
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Skipped
Build ErsatzTV Image / CI toolchain image resolves (push) Successful in 9s
Build ErsatzTV Image / Delimiter ban (release path) (push) Successful in 25s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 8m40s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 6m18s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 6m12s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m13s
probe742/combined-newest SECOND
Co-authored-by: Timothy <timothy@noreply.gitea.tblindustries.be> |