7b20dbd360cb67ef12f66f41b8d4a2f076e6e7df
100
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7b20dbd360 |
docs(release): fold #674/#688 into the v26.14.0 notes after rebasing on main
main moved while this branch was open: #725 (fix/674-688-decisions-validator) merged, so v26.14.0 now also carries the decisions-validator PyYAML cross-check. Rebased onto |
||
|
|
e997668ac4 |
chore(release): re-trigger CI for v26.14.0 release notes
The release/v26.14.0 push produced NO ActionRun records at all -- verified
against 7168 listed tasks, zero for
|
||
|
|
9a3371ecd9 |
docs(release): record the v26.14.0 release notes
Headline is ersatztv#726: Live TV stalled on any item carrying an embedded PGS/DVD bitmap subtitle, because -readrate paces an input off its furthest-behind stream and that sparse subtitle shares the video's own -i. Fixed with a capability-gated -readrate_catchup rather than the structural change the issue originally proposed, which would have removed the throttle from the frame-producing path that ffmpeg.qsv-extra-hw-frames-floor depends on. Also in this release: the H10 review-verdict gate's raced-sentinel false-open (#706/#707/#711), and two Renovate dependency bumps. No [skip ci] token -- this commit is the release tag target, and Gitea reads skip-ci from the TAGGED commit, which would suppress the release build. Refs #726 |
||
|
|
a2b3a56d93 |
Merge pull request 'fix(674,688): cross-check decision frontmatter against PyYAML; split the ceiling calibration claim' (#725) from fix/674-688-decisions-validator into main
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 + UI contracts) (push) Successful in 16m55s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 22m18s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 22m23s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 11m16s
|
||
|
|
772277e255 |
Merge pull request 'fix(726): let a lagging realtime input catch up so a sparse bitmap-subtitle stream can't pin it below realtime' (#737) from fix/726-readrate-catchup into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 35s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 36s
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 + UI contracts) (push) Successful in 29s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 13m12s
|
||
|
|
efc34a3481 |
fix(688): pin p95's inclusivity; drop a stale ratio and hedge the gap width
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 20s
PR Gates / Docs update reminder (pull_request) Successful in 32s
Review verdict / Set review-verdict status (pull_request_target) Successful in 11s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m34s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m42s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 19s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m24s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 22m10s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m46s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
PR Gates / decisions lifecycle (pull_request) Successful in 14s
review-verdict/h10 Review-verdict: MERGEABLE @ efc34a3 (base: main)
Round 7's second reviewer returned MERGEABLE on the previous head after re-measuring every figure and running a 48-mutant battery — and reported ZERO wrong or unverified numbers, which ends this branch's five-commit streak of them. It also independently confirmed the round-6 adjudication: at `f394d6ce`, the sha the record cites, the #620-era distribution really is n=167, min 2, median 26, p90 52, next value 83. All five figures correct as written. This commit clears its four non-blocking items. - `marks_tail`'s UPPER inclusivity was the last meaningful surviving mutant: `ceiling <= p95` mutated to `<` survived the whole suite. Notice-only rather than blocking, but an unpinned boundary is how a documented claim quietly stops being true — the same defect the previous commit fixed for the coarse band. Both ends now pinned; verified the mutant fails. - "the largest by ~1.6x" was TRUE at `f394d6ce` (230/147 = 1.56) and is stale today (230/198 = 1.16). Unlike the consolidation table two paragraphs down, that sentence was never scoped to a sha — so rather than re-pin a number that will rot again, it now just says "the longest", which stays true however the tail moves. - The validator docstring asserted the 60->81 gap flatly; a 70-line record existed as recently as `8f6d4f443^`, so the gap's WIDTH is more volatile than that implied. Hedged to say it is the shape as measured today, not a constant. Nothing asserts it either way. - Rewrapped a mid-sentence line break left by the previous commit. Three surviving mutants are accepted and left: the crosscheck's not-a-mapping branch is unreachable from any fixture, the None -> "" normalisation only matters for an explicit YAML null no record has, and `_frontmatter_block` returning "" instead of None is a downstream no-op. Verification: 432 scripts/tests pass; ruff at baseline parity (47, and `ruff format --check` at parity 9/9); validator exits 0 with no drift notice; corpus at p90=60, 18/183, calibrated. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
57ad5efb3f |
fix(726): quote the decision record's rule: so PyYAML doesn't truncate it
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 14s
PR Gates / Docs update reminder (pull_request) Successful in 17s
PR Gates / decisions lifecycle (pull_request) Successful in 19s
Review verdict / Set review-verdict status (pull_request_target) Successful in 6s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m48s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m27s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 25s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 22s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 5m52s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 23m52s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
review-verdict/h10 Review-verdict: MERGEABLE @ 57ad5ef (base: main)
`PR Gates / Script tests (pytest)` went red on
test_frontmatter_reader_matches_pyyaml_on_every_real_record. The rule: value was
an unquoted YAML plain scalar containing " #350's exclusion", and an unquoted
" #" starts a YAML comment -- PyYAML truncated the whole rule at "(mirroring",
so the catalog row and the mirrored MemPalace drawer carried half a sentence.
The hand-rolled frontmatter reader used by scripts/decisions_validate.py does NOT
tokenize comments, so it read the full line and reported OK; only the script-tests
job, which cross-checks the two parsers against every real record, can see this
class of defect. That is exactly what it exists for.
Fixed by single-quoting the scalar (doubling the internal apostrophe in
"image''s") and dropping the possessive from "#350's exclusion" so the token is
plain "#350". Verified both ways: PyYAML now returns the full sentence ending
"...race ahead.", and reverting the quoting reproduces the red, so the fix is
what makes the test pass rather than the test being insensitive.
Follow-up commit rather than an amend --
|
||
|
|
0ff9671393 |
fix(688): pin the minority band's constants and inclusivity; two prose corrections
Review round 7. Its adjudication of the round-6 dispute went the branch's way — measured
at `f394d6ce`, the sha the record actually cites, the #620-era distribution is n=167,
min 2, median 26, p90 52. Round 6 had measured `fefd11dff` (p90 57), a different tree.
The number stays as written.
BLOCKING FINDING: the 2%/25% constants and their inclusive boundaries were not pinned at
all. Mutating 0.02 -> 0.03, 0.25 -> 0.30, or either `<=` to `<` passed all eight
calibration tests. Those are not free parameters — they ARE the documented CI-red
thresholds, so a silent shift would quietly falsify the 38/718 figures in
docs.corpus-size-signal and docs/ci-cd.md (a strict cap reds after 37 long additions, a
strict floor after 717 short ones).
test_the_minority_band_BOUNDARIES_are_exactly_where_documented pins all four. It uses
100-record fixtures so k over the ceiling IS k%, and both 2/100 and 25/100 are exactly
representable and compare equal to the constants — true boundary cases, not near-misses.
Verified by mutation: all four now fail it.
PROSE
- corpus-size-signal said what stays blocking is "what routine growth cannot break",
immediately before explaining that 38 routine additions break it. Now "what no SINGLE
ordinary addition can break", which is what is actually true.
- docs/ci-cd.md said the fine claim is "never asserted"; it is never asserted AGAINST THE
LIVE CORPUS, and IS asserted on synthetic distributions the tests own. Corrected — the
distinction is the whole design.
Correction to an earlier commit message in this branch (
|
||
|
|
56afa4652d |
fix(726): let a lagging realtime input catch up so a sparse stream can't pin it
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 25s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 24s
Review verdict / Set review-verdict status (pull_request_target) Successful in 10s
PR Gates / decisions lifecycle (pull_request) Successful in 29s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m1s
PR Gates / Script tests (pytest) (pull_request) Failing after 1m53s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 19m4s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 22m36s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 24m58s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
-readrate throttles an INPUT and paces it off whichever of its streams is
furthest behind. An embedded bitmap subtitle (PGS/DVD) is read through the same
-i as the video -- SubtitleInputFile carries the video's path and ComplexFilter
resolves it to a stream specifier on that input, so CommandGenerator never emits
a second -i for it. Being sparse, that subtitle stream falls further behind every
second and drags video throughput down with it: measured 0.53x realtime against
the 1.0x a live client consumes at, which drains the client buffer until it
stalls. FFmpeg names the culprit itself at -loglevel warning:
[sist#0:3/dvd_subtitle] Resumed reading at pts 10.400 with rate 6.000
after a lag of 0.922s (then 1.24, 1.56, ... 3.80)
Add -readrate_catchup (6.0) to realtime video/audio inputs, capability-gated
through FFmpegKnownOption.HasOption exactly as -readrate_initial_burst is, so a
binary without it silently keeps today's behavior instead of failing to start.
The option first shipped in ffmpeg 8.0, which is NEWER than 7.1 -- hence runtime
detection rather than a version assumption. Still images and concat inputs are
excluded, mirroring #350.
Measured on prod (QSV, -threads 1, dvd_subtitle -> overlay), 45s steady-state
window after a 6s settle, replaying the captured production command line:
baseline 1.05 0.533x (x3 runs)
+ catchup 2.0 0.711x
+ catchup 6.0 1.067x (x2 runs)
+ catchup 20.0 1.067x
no subtitle overlay 1.067x (control)
Baseline reproduces the reported 0.53x and the control the reported 1.07x, so
the harness is validated on both sides. Reproduces on software libx264 too
(0.533x -> 1.067x), as expected for an input-pacing option. Raising the base
-readrate is not an alternative and was measured: 2.0 -> 0.62x, 3.0 -> 0.80x,
4.0 -> 0.80x, 6.0 -> 0.89x -- it asymptotes below realtime because the rate
ceiling was never the binding constraint.
On #529 (readrate was incidentally bounding QSV hardware-frame allocation): the
20.0-vs-6.0 row is why 6.0 was chosen, NOT evidence about allocation -- it is a
steady-state throughput number, not a count of frames in flight. Nor is the bound
safe because read rate is allocation-irrelevant: #529 measured that it is not (at
extra_hw_frames=0, 1.05 without a burst exits 0 while 1.05+burst hits ENOMEM).
Read rate changes how fast frames enter the graph, not how deep its queues are,
and #529's failure only appeared with NO pool headroom. The 64-frame floor now
guarantees headroom, so the load-bearing measurement is row 5 of that truth
table -- no -readrate at all with 64 frames -> 14 segments, exit 0 -- and a 6x
ceiling is strictly less aggressive than no throttle. Reinforcing it,
-readrate_initial_burst 8 has read flat out at the start of every playout item
since #350, so an unbounded read here is not new. A 240s QSV soak at
QsvExtraHardwareFrames=64 across 60 segment boundaries corroborates: 1.043x
sustained, zero "Cannot allocate memory" / "Could not open encoder", RSS 166MB
vs 156MB at baseline -- corroborates rather than demonstrates, since it stayed
largely caught up.
Catchup does NOT subsume the #350 burst; measured time-to-first-segment:
-readrate alone 3.71s, +burst 0.72s, +catchup alone 3.65s, both 0.67s. They fix
orthogonal metrics.
The regression test is built on a BITMAP subtitle deliberately -- a text subtitle
is fetched by the libass filter outside the demuxer, so the same assertions would
pass vacuously while the bug is fully present. It asserts on the "[0:0][0:2]overlay"
label, which is the mechanism: subtitle stream 2 resolving onto the video's input.
Every new test was mutation-checked, each producing exactly its own expected red.
Fixes #726
Decisions-Edit: yes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
2ff52d4236 |
fix(688): make the n oracle dynamic; correct a tense that asserted false history
Review round 6: one MERGEABLE with non-blocking prose, one NOT-MERGEABLE with a real test defect. Both addressed. THE n PIN DID NOT PIN ANYTHING. `assert n == 10` was checked against a fixture holding exactly ten records, so a mutation returning a constant 10 for EVERY input satisfied it — while changing the live denominator from 183 to 10, which is precisely the production defect the test was added to close. A single hardcoded count cannot tell "counts the input" from "returns this number". Now a dynamic oracle at two distinct cardinalities; verified the constant-n mutation fails it. "MOVED p90 by 21 lines" asserted a history I had not measured. 21 is TODAY's gap (60 -> 81). The actual #672 event was smaller — at that tree p90 was 60 with the next value 83, so the 62-line record moved p90 to 62 and reddened CI with a 2-line move. The capability claim is what matters and is true at both refs; the past tense was not. Changed to "can move" in the two places that asserted it, which also makes all four sites agree with docs/ci-cd.md and the validator docstring, both of which already said "could". A REVIEW FINDING I REJECTED, having measured it. Round 6 called "p90 52" wrong for the #620-era distribution, measuring 57. That measurement is at `fefd11dff`; the record cites `f394d6ce`, and at THAT sha p90 is exactly 52 (n=167, min 2, median 26). The number is correct as written and is unchanged. Recording the disagreement rather than silently keeping it: the reviewer measured a different tree than the one the claim names. Also corrected in this branch's own commit message trail: `b24c51ab5` said origin/main has three 59-line records; it has four 59s and two 60s (HEAD: four and three). The claim that survives, and the only one the code and docs now make, is that NOTHING sits between 61 and 80 at either ref — verified independently at both. Cosmetics from the same round: a dangling modifier in ceiling_calibration's docstring, a test_decisions_lib assertion message that said "field(s) differ" when faults can now also be rejections, and a sentence in corpus-size-signal that named the replacement test without saying what it asserts. Verification: 431 scripts/tests pass; ruff at baseline parity (47); validator exits 0 with no drift notice; corpus at p90=60, 18/183, calibrated. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b24c51ab51 |
fix(688): stop enumerating multiplicities, pin n and the keyless filter, de-couple the vacuity floors
Review round 5. One reviewer returned MERGEABLE with prose findings; the other found four more, two of them real test gaps. Both are addressed here. THE MULTIPLICITIES WERE WRONG AGAIN — fourth commit running. The "measured" sequence 59, 59, 60, 60 -> 81 is measured nowhere: origin/main has 59, 59, 59, 60, 60 and HEAD has four 59s and three 60s. I had even tagged it `(measured)` in a canonical decision record. So this stops enumerating them. All four sites now state only the load-bearing, stable fact: the lengths climb to the ceiling and then jump STRAIGHT to 81 with nothing in between, so one record moves p90 by 21 lines. The multiplicities change with every record added; the gap is the point. This is the same "fix the boundary, not the site" move the tests got three rounds ago, applied to prose that had failed four times. TEST GAPS - Deleting the over-tight test removed the only pin on CeilingCalibration.n: a mutation returning n=1 passed all 19 relevant tests while printing a wrong denominator in the drift notice. Pinned. - The `if r.key` filter was load-bearing in production and unpinned: main() passes the UNFILTERED list (194 entries, 11 keyless, one a 106-line "Records formerly in this file" scaffolding block), while every test handed the function a pre-filtered list — oracle and production agreed only by accident. Pinned. - The --record-ceiling 0 arm's claim that it "cannot go vacuous for any non-empty corpus" was FALSE: an empty record body is validator-valid and record_prose_lines returns 0, so a corpus of empty-bodied records has no offender at 0. Now -1, which makes the claim true. - The three `len(recs) > 100` vacuity floors were themselves growth-coupled — 83 legitimate retirements would red them even with the ceiling still calibrated, which is the #688 class in the guard rather than the assertion. Lowered to >20 where a floor is meaningful, and to plain non-empty on the derived-ceiling test, whose derivations need nothing more. - test_main_FEEDS_the_crosscheck now compares against `set(record_wing_files())` instead of a hardcoded basename, killing the same mutation with zero corpus dependence. PROSE - "ordinary growth cannot cross it — NOT immune" contradicted itself in four places. Now: no SINGLE ordinary addition can cross it; this is measured headroom, not immunity. - "trimming or archiving 15" blurred two different denominators. Trimming leaves 3/183 = 1.64%; archiving leaves 3/168 = 1.79% because the denominator moves too. Both verified, both under the floor, now stated separately. Verification: 431 scripts/tests pass; ruff at baseline parity (47 — a 121-char docstring line briefly took it to 48 and is rewrapped); validator exits 0 with no drift notice; corpus at p90=60, 18/183, calibrated; record still 60 lines. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c56dfdd539 |
fix(688): delete the last over-tight test, pin the crosscheck's INPUT, fix 4 prose defects
Review round 4, both reviewers. Both report the code path SOUND and the #688 coupling class analytically gone (rows proved, not merely observed green); one caught 28 of 30 mutations. What blocked was one over-tight test, two unpinned mutations, and prose — including two defects the PREVIOUS commit introduced while claiming to fix numbers. TESTS - Deleted test_adding_ordinary_records_cannot_RED_the_blocking_property. It appended two long records to the LIVE corpus and asserted flags_minority on the RESULT, so it crossed the cap two records before production does (56/221 vs 54/219) — a test named "cannot RED the blocking property" being a tighter tripwire than the property. Fourth instance of the #688 defect in this change. Deleted rather than tuned: both its jobs are already covered off live data (the synthetic v4/v5 contrast, and the deliberate live guard at the production threshold). - test_main_FEEDS_the_crosscheck_the_REAL_wing_files closes a mutation hole found by review: replacing `pyyaml_frontmatter_faults(record_wing_files())` with `...([])` in main() left the ENTIRE suite green. Both existing wiring tests monkeypatch the function, so they pinned that its RETURN reaches errs, never that its ARGUMENT is the corpus — the '#609 marker that printed OK while doing nothing' defect one level up, which is the exact thing the new record indicts. Verified: the mutation now fails this test. - test_main_actually_REPORTS_... went vacuous whenever the ceiling legitimately goes green (`False is False` passes with the whole warning branch deleted). Added an arm at --record-ceiling 0, which no non-empty corpus can make vacuous. - Pinned two surviving mutations: ceiling_calibration's n_over boundary (it recomputes the count, so oversized_records' exclusivity test does not cover it — `>` vs `>=` differs by the 3 records sitting exactly on the ceiling) and p95's quantile (the 95/5 fixture cannot tell 0.95 from 0.99). PROSE — two of these were introduced by the previous commit, whose stated job was fixing numbers. That is the pattern worth naming, not the individual typos. - "so ONE new record could move p90 lines" — the previous commit deleted the magnitude and left the sentence ungrammatical. Now "by 21 lines". - It also introduced a THIRD variant of the sequence it was correcting ("60, 60, 60") and missed a FOURTH site in ci-cd.md still saying "twenty lines". All four sites now read the measured 59, 59, 60, 60 -> 81, and 21 lines. - 59- and 60-line records were described as "above the ceiling"; they are at or below it. - "routine growth cannot cross it" overstated the bound: it is deliberately less sensitive, not immune. Reworded, and the THIRD and tightest arm is now documented wherever the other two appear: consolidating 15 of the 18 offenders drops below the 2% floor (verified: 3/183 = 1.64%). That is in real tension with test_oversized_records_can_go_green and is stated as accepted — at 3/183 the constant genuinely is mis-calibrated — with the remedy named: a consolidation PR that large should re-derive the ceiling in the same change. - Corrected a docstring that called the 999-ceiling failure "silently deleting the assertion"; it would go red, not silent. Verification: 430 scripts/tests pass; ruff at baseline parity (47); validator exits 0 with no drift notice; corpus at p90=60, 18/183, calibrated. The two new claims were measured, not assumed: the empty-list mutation fails the new test, and 15 consolidations reaches 1.64%. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0db56c3ebd |
fix(688): remove the last live-corpus tripwires and three fabricated/wrong numbers
Review round 3, both reviewers, NOT-MERGEABLE. Nothing needed rework — the code path was found sound and mutation-sensitive (a 17-mutation battery caught every mutation with the semantically correct test). What was left were tripwires and prose. TRIPWIRES - `assert need > 20` was the tightest live-corpus assertion left in the blocking job: it reds after 16 over-ceiling additions, while `flags_minority` — the property #688 exists to protect — survives to 36. An arbitrary threshold on a live order statistic is the ratchet wearing a different hat. Removed; the measured headroom lives in prose, where being out of date costs a doc fix rather than someone else's red build. This also removes an unbounded `while` loop that HUNG the suite rather than failing it when the ratio could not reach the cap. - test_main_reports_ceiling_drift hardcoded ceiling 999, which is not guaranteed above p95: ten valid 1000-line records make 999 calibrated and silently delete the test's only assertion. Now derived as max+1, off the tail by definition. - test_main_actually_REPORTS_the_ceiling_and_the_trend required >=1 over-ceiling record. The ceiling is ALLOWED to go green (test_oversized_records_can_go_green says so), so that would red the blocking job the day someone consolidates the last offender — punishing exactly the work the warning asks for. Restated as an IFF. - test_no_budget_flag_means_no_retirement_warning asserted no bare "RETIRED" in stderr; a legitimate stale record whose TITLE contains the word reds it. Matched precisely now. - Added the >100-record vacuity guard its siblings carry to the derived-ceiling test. NUMBERS — all three were mine, and two are the failure mode this repo calls worse than no note at all (a confident claim that was never measured): - "the lengths above the ceiling ran 60, 61, 62, 63 then jumped to 81" is FABRICATED. No record of 61, 62 or 63 lines exists at origin/main, at the #672 sha, or at the #706 sha. Measured, the sequence is 59, 59, 60, 60 then 81 — a 21-line jump, so the conclusion was if anything understated. Corrected in all three places it was repeated, including the canonical v4 row of docs.corpus-size-signal. - The crosscheck record called `decisions-guard` a REQUIRED check — introduced by the previous commit in the sentence rewritten to fix an overclaim. Verified against Gitea branch protection: `main` requires exactly `Build & test (.NET)`, `EF migration integrity` and `review-verdict/h10`. NEITHER script-tests NOR decisions-guard is required; the record now says so. - docs.corpus-size-signal said 37 additions "to reach" the cap two paragraphs above 38 "below the cap" — a same-document numeric inconsistency of exactly the class this change set out to remove. Both now state 38 to BREACH, noting 37 lands on 0.25 and passes. - Also: the old bound's accepted range is 39..229 (not 43..229 — 43 is the NEW bound's lower edge); "95% over the ceiling" was 100%; `oversized_records` said the #620 distribution began at 0 lines where the record itself says 2. Verification: 428 scripts/tests pass; ruff at baseline parity (47); validator exits 0 with no drift notice; corpus at p90=60, 18/183 over the ceiling, record trimmed to 60 lines so main ships calibrated. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b3a8826281 |
fix(688): stop asserting live-corpus order statistics anywhere in the suite
Review round 2 (both reviewers, independently) found the round-1 fix incomplete: the live-corpus coupling survived in two more tests. This is the THIRD instance of one defect class in this change, so the fix is to remove the coupling rather than patch another site. BLOCKER — test_adding_ordinary_records still asserted live order statistics. The `if before.marks_tail:` guard made the PRECONDITION conditional but left the CONCLUSION (`assert not after.marks_tail`) an assertion about the live p90. Verified: appending 16 ordinary 30-line records — nothing long, nothing unusual — makes both sides true and fires it, reddening the blocking job for an unrelated author. Exactly what #688 exists to abolish. The v4-vs-v5 contrast moved to test_v4_would_have_reddened_where_v5_holds, built on a distribution the test OWNS, reproducing the shape that matters (a sparse gap just above the ceiling). The real-corpus test now asserts only the robust claims: the additions were counted, v5 holds, and the measured headroom. Same treatment for the "bad ceiling" teeth test, which hard-coded that 200/229/230 stay rejected on the live corpus — three new 200+ line records flip it. Teeth now demonstrated synthetically; the only live-corpus assertion left is that today's ceiling is accepted, which needs 38 over-ceiling or 718 short additions to break. The IFF drift test could lose its quiet branch: one 61-line record makes BOTH the 60 and 999 ceilings drift, at which point an UNCONDITIONAL notice would pass. Both ceilings are now DERIVED — p90 itself (always calibrated, since p90 <= p90 <= p95) and max+1 (always off the tail) — so each branch is guaranteed by construction, and the test asserts it exercised both. Added the missing regression test for the typed-mapping-key TypeError: removing `key=str` now fails a test instead of only a manual probe. Corrected against measurement: the v5 row of the record's own version table still stated the REJECTED first-draft bound (`0 < f < 1/3`) — the canonical artefact contradicting both the code and its own next paragraph; accepted range is 43..180, not "roughly 45..150"; breaching the cap takes 38 additions, not 37 (37 lands exactly on 0.25, which passes under `<=`); "5x headroom below the floor" was inverted; ci-cd.md said four versions "all ratcheted" when v1 was vacuous and v2 accepted an absurd ceiling; and the crosscheck record overstated protection — script-tests is NOT a required check, so "no broken record has reached main" is procedural, not structural. Evidence the coupling is actually gone: mid-fix the corpus sat at marks_tail=False (an edit pushed this branch's own record to 61 lines, moving p90) and the suite stayed fully green. Under the old assertions that state reddened CI. The record is trimmed back to 60 so main ships calibrated and no drift notice nags. Verification: 428 scripts/tests pass; ruff at baseline parity (47); validator exits 0 with no drift notice; corpus at p90=60, 18/183 over the ceiling. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
80818aa294 |
fix(674,688): address independent review — restore the coarse bound's teeth
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 33s
PR Gates / Docs update reminder (pull_request) Successful in 31s
PR Gates / decisions lifecycle (pull_request) Successful in 41s
Review verdict / Set review-verdict status (pull_request_target) Successful in 12s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m14s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m32s
PR Gates / Script tests (pytest) (pull_request) Successful in 2m8s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m53s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 20m30s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 23m19s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Two independent cold reviews (one cross-family) agreed on the top two findings. 1. The #688 fix was defeated by its own complement test. test_main_is_QUIET_about_ drift asserted the drift notice was ABSENT while running main() over the LIVE corpus — whose failure condition is bit-for-bit v4's assertion, in the same blocking job, three functions down. p90 sat exactly on 60, so one over-ceiling record would have reddened it. Replaced with an IFF test that uses ceiling_calibration as its oracle, so it asserts the WIRING rather than the corpus's current state, plus a guard that at least one branch fires. 2. The coarse bound was nearly unfalsifiable. `0 < fraction_over < 1/3` accepted EVERY ceiling from 39 to 229 on the real corpus — including the ceiling of 200 my own docstring offered as the case it catches, because one 230-line record keeps the count nonzero. That claim was simply false and is corrected. The floor is now a FRACTION (2%) and the cap 25%, which rejects 200/229/230 and 20, and accepts roughly 45..150. Headroom measured, not estimated: 37 consecutive over-ceiling additions, against ONE record to break v4. 3. yaml.safe_load raises a bare ValueError, not a YAMLError, on a well-shaped but impossible date (stale-after: 2026-06-31), which escaped as a traceback and killed the validator on any machine with PyYAML. The except is now deliberately broad, with a test. 4. PyYAML returns TYPED mapping keys, so a stray `1: x` made sorted(set|set) raise TypeError. Sorted with key=str. 5. The headroom prose was arithmetically wrong (~42/~40 where the real values are 63/64; each addition moves numerator AND denominator) and the record counts were stale. Corrected against measurement. 6. test_adding_ordinary_records passed identically with its two additions removed. It now asserts the additions were counted, and that they break the v4 property while leaving v5 satisfied — guarded by `if`, never asserted, since whether v4 currently holds is a fact about the live distribution and asserting it would rebuild the ratchet. Also recorded honestly in docs.frontmatter-pyyaml-crosscheck: decisions-guard installs no PyYAML, so in CI the cross-check always skips and script-tests already caught both hazards — the CI delta is close to zero and the real fix is the local loop plus the tool/suite agreement. And the new record was trimmed 64 -> 58 prose lines: at 64 it moved p90 to 64 by itself, i.e. this PR would have reddened the old blocking job. That is now cited in the test as the live demonstration. Verification: 426 scripts/tests pass; ruff at baseline parity (47); validator exits 0; corpus back to p90=60, 18/183 over the ceiling, marks_tail and flags_minority both true. Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9d2b30dc3b |
fix(674,688): cross-check frontmatter against PyYAML; split the ceiling calibration claim
Two defects in scripts/decisions_validate.py, fixed together because they share the validator and its pytest suite. #674 — the validator reported OK on frontmatter PyYAML rejects. The hand-rolled reader is deliberately dependency-free (decisions-guard and the Husky hooks install nothing), so it cannot see a bare apostrophe closing a single-quoted scalar. Hit twice in one session by two independent agents. `pyyaml_frontmatter_faults()` now cross-checks the parse against PyYAML whenever PyYAML is importable, and is SKIPPED with a ::notice:: when it is not — the read path stays dependency-free. The two known hazards fail differently and the fix covers both: the apostrophe makes PyYAML reject the document, while an unquoted ` #` parses fine and silently TRUNCATES the value. So the check compares parsed results key by key rather than try/except-ing the load, which is also what makes it generalize past the two known characters. PyYAML wrote these files, so on disagreement it is authoritative and the file is the defect. The comparison has one implementation, called by the validator and by the existing test_decisions_lib agreement test, so the tool and the suite cannot drift. #688 — test_real_corpus_ceiling_sits_at_the_TAIL_BOUNDARY asserted p90 <= 60 <= p95 in the BLOCKING script-tests job. p90 sat exactly on the ceiling and the distribution above it is sparse, so one ordinary record moved p90 by twenty lines and reddened CI for whoever wrote it; it reproduced twice live (#672, #706) and both times the only in-scope remedy was trimming the new record to fit the constant. v5 splits the claim by robustness instead of hunting for a better single assertion. The blocking test now asserts only the coarse, non-ratcheting property (the ceiling flags a nonempty proper minority, 0 < fraction_over < 1/3); the fine tail-boundary claim is measured every run and REPORTED as a ::notice::, on the same reasoning stale_records already uses — a constant going out of date is the passage of corpus growth, not a defect in the commit under test. The fine property is still asserted, against synthetic distributions the test owns. The ceiling stays 60. Verification: 424 scripts/tests pass; ruff at baseline parity (47 before and after); the cross-check is clean on all 183 real records; a positive control pins that record_wing_faults alone still reports both hazard files as clean, so the new red cannot pass for the wrong reason; and a test demonstrates that appending #672's 62-line and #687's 107-line records to the real corpus does not red the blocking property. Docs: new record docs.frontmatter-pyyaml-crosscheck, docs.corpus-size-signal updated for the v5 split, catalog regenerated, docs/ci-cd.md updated for both. fixes #674 fixes #688 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
aa79ec59c9 |
Merge pull request 'fix(706,707,711): fence the review-verdict write on the timeline retarget count' (#723) from fix/706-verdict-status-serialization into main
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 17s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 29s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 30s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9m31s
|
||
|
|
fe3d29276a |
fix(706): count a raced SENTINEL, not only a raced human verdict
PR Gates / decisions lifecycle (pull_request) Successful in 19s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 20s
PR Gates / Docs update reminder (pull_request) Successful in 21s
Review verdict / Set review-verdict status (pull_request_target) Successful in 7s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m29s
review-verdict/h10 Review-verdict: MERGEABLE @ fe3d292 (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m54s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 10s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 7s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 15m3s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 15m49s
Round-5 cold review: the post-write check counted only human `Review-verdict:` rows above the high-water mark, which is not sufficient under the run overlap this branch measured. Sequence, all inside that regime, runs A and B on the same exempt-classified sha: the human BLOCKED lands BELOW A's mark (so A cannot see it), B masks it with an exemption `success`, and only afterwards writes the sentinel. A then finds nothing human above its mark, does not repair, and posts its own `success` on top of the sentinel. The human rejection is permanently green and every later run re-derives it — the repair race failing toward SUCCESS, while the record states it fails toward `pending`. The filter now counts two row shapes above the mark: a human verdict (non-null creator, `Review-verdict:` description) OR a machine sentinel (null creator, description exactly $REPAIR_DESC). A then repairs and both runs converge on the fixed point. It cannot false-fire: a pre-existing sentinel would have been seen at the FIRST read and forced the pending path, and this block only runs after a `success`, so a sentinel above the mark can only have been written mid-flight by another run. Mutation-verified on both halves independently — dropping the sentinel alternation reddens the new test; dropping the human half reddens the original race-2 test — so neither can be removed without a test noticing. Refs #706 |
||
|
|
a8bbd74a64 |
fix(706): never replace a sentinel with a non-sentinel
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 14s
PR Gates / Docs update reminder (pull_request) Successful in 15s
PR Gates / decisions lifecycle (pull_request) Successful in 20s
review-verdict/h10 Awaiting review verdict for a8bbd74
Review verdict / Set review-verdict status (pull_request_target) Successful in 8s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m31s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m52s
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 6s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m39s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m22s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-4 cold review: the mid-run sentinel guard tested `state = success`, which
is one branch too narrow. A run can reach the POST on `state=pending` carrying
the GENERIC description — most realistically after a transient enumeration
failure (`complete != yes`) — and such a run passed the success-only guard,
passed the fence, and overwrote the sentinel with ordinary text. The next run
then saw no sentinel, re-derived, and posted `success`: the same buried human
rejection as the round-2 defect, reached in two steps instead of one.
The guard now compares the DESCRIPTION rather than the state:
if [ "$ex_repair" = yes ] && [ "$desc" != "$REPAIR_DESC" ]
"Never replace a sentinel with a non-sentinel." This is strictly more general
and exactly as precise, because the carry-forward branch guarantees that a
sentinel seen at the FIRST read already sets `desc` to the sentinel — so the
guard cannot fire on the ordinary repaired-head path and the fixed point stays
intact.
It also makes the code match the decision record, which already stated the
general property ("a run whose last-moment re-read finds a sentinel it did not
see at its FIRST read ABSTAINS instead of posting") while the code implemented
only the success case. Of the two, the code was the one that had to move.
Mutation-verified on both clauses independently: reverting to the success-only
condition reddens the new pending-path test; dropping the description check
reddens the fixed-point test and the sentinel-from-the-start control.
Refs #706
|
||
|
|
5077408528 |
fix(706): abstain when a repair sentinel appears mid-run
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Docs update reminder (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 18s
review-verdict/h10 Awaiting review verdict for 5077408
Review verdict / Set review-verdict status (pull_request_target) Successful in 10s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m46s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m5s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 10s
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 20m47s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 23m42s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-3 cold review: `ex_repair` was recomputed by the last-moment re-read but never consulted after it, so the POST wrote the `$state` frozen at classification time. A stale overlapping run therefore posted its `success` straight over a sentinel another run had just written — burying a human rejection with no repair (the human row sits below the stale run's own high-water mark) and no log entry. This is the one path in the design that failed toward SUCCESS rather than `pending`, so it was not covered by the recorded residual, and it is reachable through exactly the run overlap this branch measured live (probe PR #722: the older run finished 20s after the newer one started). The guard is exact rather than conservative: a sentinel present at the FIRST read forces `state=pending`, so `success` together with `ex_repair=yes` at re-read time can only mean the sentinel arrived mid-run. Abstaining is then strictly correct and, unlike the retarget fence, needs no successor run — the sentinel row is already `pending` and already carries the re-post instruction. Mutation-verified three ways: removing the guard reddens the new mid-run test while its positive control stays green; making it unconditional on `ex_repair` reddens the fixed-point test and the positive control, proving the condition is precisely scoped and not merely present. Also strengthens the mark-ordering test to pin the status-history FETCH as well as its initialisation, closing the refactor evasion review flagged; sliding the fetch past the re-read now reddens it. Refs #706 |
||
|
|
63040296f4 |
fix(706): make the repair sentinel a fixed point, not a two-event delay
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 13s
PR Gates / Docs update reminder (pull_request) Successful in 17s
PR Gates / decisions lifecycle (pull_request) Successful in 19s
review-verdict/h10 Awaiting review verdict for 6304029
Review verdict / Set review-verdict status (pull_request_target) Successful in 35s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m44s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 18s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 15s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m18s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 16m0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m6s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-2 cold review found the round-1 sentinel self-clobbering: the branch refused the exemption but fell through to the shared else, which posts the GENERIC "Awaiting review verdict" description — erasing the very marker the refusal depends on. The next run saw an ordinary machine `pending`, re-derived it, and posted `success`, burying the human rejection two events after the repair instead of one. The single-hop test passed throughout, and the positive control asserting that an ordinary machine `pending` DOES re-derive was itself the proof of the second hop. Durability is a fixed point, and only a chain can assert a fixed point, so the new test runs the job twice and feeds run N's own posted description in as run N+1's existing status. Keyed on `ex_repair` alone rather than on the exempt path: the fact recorded is "a human verdict was lost on this sha", a property of the sha rather than of this run's classification. Verified by mutation — restoring the defect turns the chained test RED while the single-hop test stays GREEN, which is exactly why the chain was needed. Refs #706 |
||
|
|
8f6d4f4432 |
fix(706,707,711): fence the review-verdict write on the timeline retarget count
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Docs update reminder (pull_request) Successful in 15s
PR Gates / decisions lifecycle (pull_request) Successful in 23s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 23s
review-verdict/h10 Awaiting review verdict for 8f6d4f4
Review verdict / Set review-verdict status (pull_request_target) Successful in 20s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m29s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m26s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m56s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m59s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m41s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Three related defects in the `review-verdict/h10` gate, all surfaced by the cross-family review of PR #705. #706 race 1 — a stale run could overwrite a fresher verdict, permanently. The race was reproduced live rather than reasoned about (Gitea 1.25.4): with every other workflow stripped, probe PR #722 showed run 7520 (`opened`) finishing 20s AFTER run 7521 (`synchronize`) started. `pull_request_target` runs for one PR genuinely overlap, older finishing last. The issue proposed serializing with a non-cancelling concurrency group. That is REFUTED by measurement: with the group active, runs 7528/7529 still overlapped and 7528 ended 36s after 7529 began. A first probe appeared to show the group working — a negative control with no `concurrency:` key at all showed the same cancellations, revealing Gitea auto-cancels superseded `push` runs on its own and the probe had measured that, not the group. The auto-cancel does not extend to `pull_request_target`. The fix leaves the runs unserialized and instead makes an overtaken run decline to write: count `change_target_branch` events on the PR timeline at start and again just before the POST, and post nothing if the count moved. The COUNT is the key because the branch NAME is ABA-vulnerable (`main -> S -> main` reads `main` at both ends — how #698 route 1 forged its exemption). Abstaining is a handoff, not a stall: every retarget fires `edited`, so the event that makes a run abstain has already queued its successor. `updated_at` was rejected as the key precisely because it moves for comments/labels, which queue nothing. #706 race 2 — a human BLOCKED landing in the unclosable window between the pre-POST re-read and the POST was silently turned green. After an exemption `success` the job now re-reads the per-POST history and repairs its own status to `pending` if a human verdict appeared above a high-water mark taken just before the write. The repair is `pending`, never a copy of the human's state. The id comparison is load-bearing: a presence test would fire forever on a base-mismatched verdict and deadlock that PR's exemption. #707 — `pr-changed-files.sh` bound `.base.ref` and `.head.sha` across the enumeration but never `.base.sha`, so an ordinary advance of `main` mid-paging could drop a code path from an offset-paged diff and leave a complete-looking docs-only list. Now bound from the JSON already fetched (no new round trips). #711 — `.codex/` added to PROTECTED. It mirrors `.claude/hooks/` byte for byte, including the merge-consent hook, so the "a PR that can weaken the gate cannot exempt itself" rule had an incomplete path list. Latent today (untracked), live the moment anyone tracks it. Residuals are stated, not implied: a retarget inside the final round-trip, and the repair being itself a read-then-write. Gitea's status API has no compare-and-set, so neither reaches zero; both now fail toward `pending`. Tests: 398 pass in scripts/tests. Each new guard was mutation-checked — the fence's motion comparison, the untrusted-count gate, the repair POST and the id high-water mark were each neutered in turn and the intended test went red while its positive control stayed green. fixes #706 fixes #707 fixes #711 Decisions-Edit: yes |
||
|
|
7cd71327b0 |
Merge pull request 'chore(deps): update dependency cliwrap to 3.10.4' (#717) from renovate/cliwrap-3.x into main
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 18s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 29s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 31s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 11m9s
Reviewed-on: #717 |
||
|
|
53e6be8390 |
Merge branch 'main' into renovate/cliwrap-3.x
PR Gates / Docs update reminder (pull_request) Successful in 22s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 19s
review-verdict/h10 Exempt: authored by the 'renovate' bot account, touches no protected path, and changes only dependency manifests
Review verdict / Set review-verdict status (pull_request_target) Successful in 24s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m14s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 58s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m6s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m3s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m7s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m56s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
PR Gates / decisions lifecycle (pull_request) Successful in 16s
|
||
|
|
b99812eb8b |
Merge pull request 'chore(deps): update dependency jetbrains.resharper.globaltools to 2025.3.5' (#718) from renovate/jetbrains.resharper.globaltools-2025.x into main
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 41s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 45s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 45s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 13m2s
Reviewed-on: #718 |
||
|
|
03662dcdfd |
Merge branch 'main' into renovate/cliwrap-3.x
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 17s
PR Gates / decisions lifecycle (pull_request) Successful in 51s
PR Gates / Docs update reminder (pull_request) Successful in 47s
review-verdict/h10 Exempt: authored by the 'renovate' bot account, touches no protected path, and changes only dependency manifests
PR Gates / Script tests (pytest) (pull_request) Successful in 1m15s
Review verdict / Set review-verdict status (pull_request_target) Successful in 24s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m37s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m8s
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 13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m31s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
|
||
|
|
aaa4e869b8 |
Merge branch 'main' into renovate/jetbrains.resharper.globaltools-2025.x
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 19s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 24s
PR Gates / Docs update reminder (pull_request) Successful in 20s
PR Gates / decisions lifecycle (pull_request) Successful in 32s
review-verdict/h10 Exempt: authored by the 'renovate' bot account, touches no protected path, and changes only dependency manifests
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m39s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m4s
Review verdict / Set review-verdict status (pull_request_target) Successful in 2m7s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 18m27s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 23m8s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 24m23s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
|
||
|
|
9dc360c9fa |
Merge pull request 'docs(release): record the v26.13.0 release notes' (#716) from release/v26.13.0 into main
Build CI Toolchain Image / Build & push CI image (push) Successful in 28s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 8m34s
Build ErsatzTV Image / Functional E2E (curl + UI 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 6m17s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m40s
|
||
|
|
9928be805f |
Merge pull request 'chore(deps): batch three Renovate patch bumps (supersedes #679, #680, #681)' (#714) from chore/renovate-batch-2026-07-30 into main
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 16s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 27s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 28s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 10m54s
Build CI Toolchain Image / Build & push CI image (push) Successful in 9m5s
Dependency vulnerability scan / NuGet vulnerable packages (push) Successful in 1m10s
Renovate / Renovate (push) Successful in 2m20s
|
||
|
|
fbbdaeca3c |
chore(deps): batch three Renovate patch bumps
PR Gates / Docs update reminder (pull_request) Successful in 22s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 25s
PR Gates / decisions lifecycle (pull_request) Successful in 32s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 58s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 57s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m8s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m23s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m9s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m47s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
review-verdict/h10 Review-verdict: MERGEABLE @ fbbdaec (base: main)
Review verdict / Set review-verdict status (pull_request_target) Successful in 5s
Consolidates the three open Renovate PRs into one change so they land on a single CI pipeline instead of three. They all edit Directory.Packages.props, so merging them individually would force a rebase + full re-run for each remaining PR. CliWrap 3.10.2 -> 3.10.3 Meziantou.Analyzer 3.0.115 -> 3.0.129 SQLitePCLRaw.bundle_e_sqlite3 3.0.3 -> 3.0.4 Also refreshes the #8 security-pin comment, which named 3.0.3 explicitly. Renovate only rewrites the version attribute, so its own PR would have left that comment contradicting the line directly beneath it. The pin's intent is unchanged: stay on the 3.x line that ships the patched native SQLite (GHSA-2m69-gcr7-jv3q), and 3.0.4 still satisfies Microsoft.Data.Sqlite's `>= 2.1.10`. All three original PRs went red on 2026-07-27, but none of the failures reached any code. The runner host had exhausted its disk at ~03:20 UTC: tar cache-restore failing with "No space left on device", SQLite Error 13 "database or disk is full", and ErsatzTV refusing to boot for want of 128 MB of free space. #681's migration job in particular died during cache restore, before either the SQLite or MySQL half ran, so the native-bundle bump was never actually exercised there. Verified locally on this combined change: - dotnet build -c Release: 0 errors; zero MA/S/CA analyzer diagnostics, so the Meziantou 3.0.115 -> 3.0.129 jump introduces no new rules that bite - full test suite: 4440 passed, 0 failed across all 7 test projects - SQLite model drift clean + all migrations applied to a fresh DB, which is the exact job that was red on #681 Supersedes #679, #680, #681. |
||
|
|
f9cbd152bc |
Merge pull request 'chore: ignore .codex/, and stop shipping a plaintext credential in docs' (#712) from chore/codex-ignore-and-credential-redaction into main
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 + UI contracts) (push) Successful in 16m45s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 20m5s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 22m4s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m18s
|
||
|
|
980da6db00 |
chore: ignore .codex/, and stop shipping a plaintext credential in docs
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 16s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 15s
PR Gates / decisions lifecycle (pull_request) Successful in 22s
Review verdict / Set review-verdict status (pull_request_target) Successful in 21s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m15s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m29s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 17m25s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m3s
review-verdict/h10 Review-verdict: MERGEABLE @ 980da6d (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m44s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
.codex/ is generated by `codex exec` as a machine-local mirror of the .claude hooks. It is deliberately NOT tracked even though .claude/ is (17 files): its config.toml embeds a plaintext Gitea credential and absolute /Users paths, so committing it would leak the credential and would not be portable anyway. Ignoring it also unblocks scripts/refresh-shared-checkout.sh, which refuses on a dirty tree. Separately, docs/handoffs/rest-api.md carried the same credential inline; it now references $ETV_GITEA_BASICAUTH like every other doc. NOTE this does not purge git history — the literal appears in 12 earlier commits and is still recoverable there. Refs: #698 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
81be685df9 |
Merge pull request 'docs(698): correct the Renovate auto-pass rule in CLAUDE.md' (#710) from docs/698-claudemd-renovate-rule into main
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 + UI contracts) (push) Successful in 38s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 38s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 39s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 10s
|
||
|
|
1eca9b0c11 |
docs(698): correct the Renovate auto-pass rule in CLAUDE.md
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 16s
PR Gates / Docs update reminder (pull_request) Successful in 18s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 19s
PR Gates / decisions lifecycle (pull_request) Successful in 20s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 39s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 38s
review-verdict/h10 Exempt: docs-only change (no code, no protected path)
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 38s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 38s
Review verdict / Set review-verdict status (pull_request_target) Successful in 24s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
PR Gates / Script tests (pytest) (pull_request) Successful in 1m0s
CLAUDE.md still described the bot exemption as identity-only (auto-passed unless a protected path is touched). Since #698 it also requires EVERY changed path to be a dependency manifest — a bot account does not attribute the code at a head. CLAUDE.md is loaded every session, so a stale rule here is worse than a stale doc. Refs: #698 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
a3458e6e2c |
Merge pull request 'fix(698): bind the base, constrain the bot exemption by content, re-derive unattributable successes' (#705) from fix/698-exemption-provenance into main
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 37s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 37s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 38s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 16m20s
|
||
|
|
57e33f9937 |
chore(698): drop a trailing blank line at EOF
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 15s
PR Gates / Docs update reminder (pull_request) Successful in 18s
PR Gates / decisions lifecycle (pull_request) Successful in 24s
Review verdict / Set review-verdict status (pull_request_target) Successful in 12s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m17s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m0s
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 / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m31s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 17m3s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
review-verdict/h10 Review-verdict: MERGEABLE @ 57e33f9 (base: main)
Nit from review round 6 (git diff --check). No behaviour change. Refs: #698 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
fe00e0d71f |
fix(698): compare the recorded base exactly, never parse it out
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 37s
PR Gates / Docs update reminder (pull_request) Successful in 40s
PR Gates / decisions lifecycle (pull_request) Successful in 45s
review-verdict/h10 Awaiting review verdict for fe00e0d
Review verdict / Set review-verdict status (pull_request_target) Successful in 14s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m23s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m19s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m34s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m12s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 21m4s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 24m7s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Review round 5 returned BLOCKED with one High, and it needed no forgery and no #697 — just a branch name. `main)evil` IS A VALID GIT BRANCH NAME (`git check-ref-format --branch 'main)evil'` succeeds). A genuine human verdict earned while head H targeted it is written `(base: main)evil)`. Truncating at the first `)` yields exactly `main`, which matches a PR that has since been retargeted onto `main`, so the verdict is inherited over a completely different diff. I had asserted the opposite in a code comment one commit earlier — that a `)` in a branch name "mismatches — safe direction". That was generalised from `feat/foo)bar`, which does mismatch, and is false for EVERY branch whose name starts with the target base. Two attempts at extracting this value have now been defeated (`##` last-marker by an appended marker, `#` first-marker by this), so the lesson is the shape, not the off-by-one: do not parse a value out of user- or attacker-influenced text when you can compare against the exact expected literal instead. The description must now END with the literal `(base: <this PR's base>)` AND contain exactly ONE marker — the marker count kills the append trick without having to decide which occurrence is authoritative. Pure shell (`${#}` arithmetic), no truncation to abuse. Verified across all six shapes, including a PR that legitimately targets `main)evil` (accepted) and `(base: )` (rejected). Absent markers remain accepted, since verdicts predating #632 carry none. Mutation-verified: restoring the truncating parse reddens only the new paren test, while the appended-marker, matching-base and legacy tests stay green. 385 tests pass. Note for the record: pytest has never executed inside the review sandbox in any of the five rounds, so the suite has only ever been run here. Refs: #698 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ef92b46dd2 |
fix(698): parse the recorded base at its FIRST occurrence, not its last
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 17s
PR Gates / Docs update reminder (pull_request) Successful in 19s
PR Gates / decisions lifecycle (pull_request) Successful in 28s
review-verdict/h10 Awaiting review verdict for ef92b46
Review verdict / Set review-verdict status (pull_request_target) Successful in 23s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m21s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m31s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m31s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m40s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m35s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m29s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Self-found while writing the round-5 review brief, by asking what an attacker who can influence the status description (#697) could do to the parse I had just added. `${ex_desc##*"(base: "}` is greedy, so it reads the LAST occurrence. A description of `Review-verdict: MERGEABLE @ abc1234 (base: probe/scratch) (base: main)` therefore parsed as `main`, matched the PR's base, and the verdict was inherited — reopening the exact hole the base check was added to close, one commit earlier. Measured both forms before choosing: first-match yields `probe/scratch`, mismatches, and fails closed. Two adjacent cases confirmed to fail in the safe direction: a `)` inside a branch name truncates the value (mismatch), and an empty `(base: )` is present-but-different (mismatch), so neither is waved through by the legacy-absent-base allowance. Tests for both, and the appended-base test is mutation-verified: restoring `##` reddens it. 384 tests pass. Refs: #698 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e7bae06385 |
fix(698): review round 5 — a human verdict formed against ANOTHER base is no longer inherited
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 13s
PR Gates / Docs update reminder (pull_request) Successful in 21s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 23s
review-verdict/h10 Awaiting review verdict for e7bae06
PR Gates / decisions lifecycle (pull_request) Successful in 31s
Review verdict / Set review-verdict status (pull_request_target) Successful in 21s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m5s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m27s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m23s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 20m17s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m13s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-4 cross-family review returned BLOCKED with a single Medium; the three round-3 items were confirmed actually fixed. THE SHA-BINDING WAS ESCAPABLE THROUGH THE HUMAN PATH, not the exemption path. The short-circuit identified a human verdict by creator + `Review-verdict:` prefix and then exited before looking at the base. So: earn a GENUINE `success` on head H while it targets a scratch base with a benign diff, then retarget H onto `main`, where its diff carries unreviewed code. Creator real, prefix real, status inherited — a green required check over code nobody reviewed. `post-review-verdict.sh` has recorded the reviewed base in the description since #632; this gate simply never read it. The merge-consent hook did compare it, but that is advisory and covers only its own path: a merge through the Gitea UI or API sees nothing but the status. The gate now rejects a verdict whose recorded base differs from the PR's. An ABSENT base is deliberately NOT a mismatch — verdicts predating #632 carry none, and re-deriving over one would un-approve a genuinely reviewed head. Only present-and-different is rejected, which is exactly the escape. Tests: the mismatch case, plus two positive controls (matching base still short-circuits; a legacy no-base verdict still short-circuits) so the check cannot pass by blanket rejection. Mutation-verified: removing the check reddens only the mismatch test. Also from round 4: sharpened the docstring of test_the_classify_step_runs_without_SHELL_ERRORS. It catches guards that die NOISILY; it is not a general liveness check, since a clean mutation like hardcoding n_protected=0 emits nothing. The branch-discriminator test is the actual liveness guard. Claiming otherwise would have made a cheap net look like a strong one. And fixed a dangling decision key I had just introduced: the base-in-description convention belongs to `release.verdict-status-check`, not the `ci.verdict-records-base` I invented — the breadcrumb hazard our own retrieval rules warn about. 382 tests pass. Refs: #698 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d4c600149d |
fix(698): review round 4 — the PROTECTED guard was DEAD; define before use, fail closed, fix prescriptive docs
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 16s
PR Gates / Docs update reminder (pull_request) Successful in 19s
PR Gates / decisions lifecycle (pull_request) Successful in 22s
review-verdict/h10 Awaiting review verdict for d4c6001
Review verdict / Set review-verdict status (pull_request_target) Successful in 13s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m23s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 22s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m38s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 16m30s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 18m18s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-3 cross-family review returned BLOCKED with 3 Mediums. The first was serious
and self-inflicted.
THE PROTECTED GUARD WAS A NO-OP. Round 3's `count_matching` / `count_not_matching`
helpers were defined AFTER the classification chain that calls them, so
`count_matching` was `command not found` on every run, `$( )` yielded an empty string,
`[ "" -gt 0 ]` errored, and the `elif` was simply skipped — the protected-path check
never executed at all. Confirmed by direct execution before fixing.
Three "protected path" tests stayed GREEN throughout, because a protected path is also
not a manifest and not docs-only, so the job still reached `pending` down a different
route. Asserting the STATE could not distinguish a working guard from a dead one. The
mutation battery missed it too: I had mutated the predicates, not their reachability.
Fixed three ways:
* helpers are defined immediately after `gh()`, before any use;
* the three counts are evaluated ONCE at TOP LEVEL and validated numeric, because
`exit 1` inside `$( )` leaves only the subshell and, with the substitution sitting
in a conditional, `set -e` never fires either — so a grep error had been silently
reading as "no match". A non-numeric result now aborts with nothing posted, and an
absent required check blocks the merge;
* the helpers return a non-numeric sentinel instead of trying to `exit`.
Verified: an invalid regex now exits 2 and posts NOTHING (previously it classified and
posted). Renaming the helper at its definition turns six tests red.
TESTS, aimed at the failure mode rather than the symptom:
* assert the DISCRIMINATOR (the job's `Decision:` reason line), not the outcome —
when several branches yield the same verdict, the verdict cannot tell you which ran.
A first draft of this test asserted the status description and failed against a
WORKING guard, because for `pending` the description is constant;
* a cheap stderr sweep for `command not found` / `integer expression expected` /
`unbound variable` across four representative PR shapes. Each of those makes an `if`
condition merely false while the job exits 0 and posts a plausible status, so this
catches a whole family of silently-skipped guards.
DOCS. The record and ci-cd.md still PRESCRIBED the here-string that round 3 removed —
following them would have reintroduced the temp-storage failure. Both now prescribe
counting, define-before-use, top-level evaluation and numeric validation. The workflow's
measurement paragraph still said the npm manifests "are included" three lines above the
note saying they are excluded; corrected.
379 tests pass.
Refs: #698
Decisions-Edit: yes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
d8bd1dcba9 |
fix(698): review round 3 — count instead of matching, re-read before the POST, fix stale docs
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 18s
PR Gates / Docs update reminder (pull_request) Successful in 23s
PR Gates / decisions lifecycle (pull_request) Successful in 31s
review-verdict/h10 Awaiting review verdict for d8bd1dc
Review verdict / Set review-verdict status (pull_request_target) Successful in 36s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m13s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 19s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 16s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m28s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m59s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Round-2 cross-family review returned BLOCKED: 2 High + 3 Medium. HIGH — here-strings traded one fail-open for another. `grep -q… <<< "$data"` fixes the SIGPIPE inversion, but bash materialises a large here-string via temporary storage, so it fails when temp space is full or unwritable — and since these sit inside `if`/`!`, that failure flips the predicate exactly as SIGPIPE did. It did NOT reproduce on my bash 3.2, DID on the reviewer's Linux bash 5.x, and CI is Linux; the disagreement is itself the argument for a construct that cannot fail either way. Path predicates now COUNT with `grep -c`, which drains stdin (no early exit, no SIGPIPE) over an ordinary pipe (no temp file), and grep's status is read honestly: exit 1 means "zero matches", a legitimate answer, while >1 is a real error that FAILS THE JOB rather than silently reading as "no match". `set -e` does not catch these on its own — they sit in command substitution inside a conditional. Verified correct under 171KB input AND an unwritable TMPDIR. The description test became a `case` prefix match, removing another pipeline from a security predicate. New record `ci.grep-q-pipefail-inversion` covers the whole class. HIGH — a human verdict landing mid-run was still overwritten, and the code claimed otherwise. The job read statuses once, classified over several round-trips, then posted: a reviewer posting BLOCKED in between had it replaced by an exemption `success`, turning an explicit rejection into a merge. Added a re-read immediately before the POST which refuses to write over a human verdict found then. The heading no longer says "never overwrite" — it cannot promise that, since there is no compare-and-set on Gitea's status API. Remainder tracked as #706. MEDIUM — documentation was stale in three places, all mine. The record's frontmatter `rule:` still listed the npm manifests (I fixed the body and forgot the frontmatter, so the canonical rule AND the generated catalog were wrong); docs/ci-cd.md still said `edited` was absent from `types:`, contradicting a section I had just updated; and the workflow header still implied the `edited` re-run settles the ABA race. All corrected to say detection, not atomicity. TESTS. 373 pass. New: a mid-run human verdict via a status stub that returns nothing on the first read and BLOCKED on the re-read, and large-input regression tests for the ADVISORY hook, which had none — the copy with less authority is the one that quietly keeps a bug (#649's whole point). Mutation-verified: reverting the hook predicate, the workflow predicates, or the pre-POST re-read turns exactly the intended tests red while every positive control stays green. Refs: #698 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
bafb487eaa |
fix(698): review round 2 — close a PRE-EXISTING SIGPIPE inversion, narrow the bot allow-list, correct two overclaims
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 15s
PR Gates / Docs update reminder (pull_request) Successful in 24s
PR Gates / decisions lifecycle (pull_request) Successful in 33s
review-verdict/h10 Awaiting review verdict for bafb487
PR Gates / Script tests (pytest) (pull_request) Successful in 59s
Review verdict / Set review-verdict status (pull_request_target) Successful in 34s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m30s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m36s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m9s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 21m17s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 22m6s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Cross-family adversarial review returned BLOCKED with 3 Blockers + 2 Highs. Two were verified independently before acting on them. BLOCKER 1 (pre-existing on main, not introduced here). `producer | grep -q…` inverts under `set -o pipefail`: grep exits at its first match, the producer takes SIGPIPE and exits 141 once the list exceeds the pipe buffer, so a MATCH is reported as a FAILED pipeline. Reproduced at 1901 paths / ~171KB, inside the enumerator's 2000-file cap: * `A.cs` + 1900 docs paths -> docs_only=yes, status 141 (a C# PR exempted) * `.gitea/…` + 1900 docs -> the PROTECTED guard MISSES entirely The second reaches a green required status on a PR rewriting the gate, with no retarget, no bot account and no forged status. This construct shipped with the original docs-only check (review-verdict.yml:257 on main), so it was live. Fixed in both the enforced gate and the advisory hook by using here-strings, which have no writer to signal. New record `ci.grep-q-pipefail-inversion`. BLOCKER 2 (mine). `web/package.json` / `web/package-lock.json` are removed from BOT_MANIFESTS. renovate.json enables only nuget/github-actions/dockerfile, so npm is unmanaged here and the entry bought nothing — while package.json `scripts` are EXECUTED by CI (npm ci, npm run build). It widened an exemption onto a code-execution path for no benefit. BLOCKER 3 + HIGH (documentation was wrong, code unchanged). The claim that `edited` made the retarget residual "non-durable" is retracted: runs are not serialized, so a stale run can post `success` after the reclassifying run posts `pending`. The ABA transition is narrowed and observable, NOT closed. Likewise the provenance check asks "posted by a user credential", not "posted by a reviewer" — ETV_STATUS_AUTH is basic auth, so a #697 forgery gets a non-null creator AND an attacker-chosen description and is preserved as human. Both now stated at full strength. TESTS. 4 large-input cases crossing the pipe buffer, each paired with a large-input POSITIVE control so "large lists now fail closed" (a deadlock) cannot pass as a fix. Verified by mutation: reverting the here-strings turns all three negatives red while the control stays green. Two of my own weak tests fixed — the "base advances" case called head_moves_to(SHA) with the already-current sha (a duplicate positive control, now a structural assertion that the comparator is .base.ref and never .base.sha), and the arity test counted five arguments without checking the fifth was the base. The whole class was invisible because every previous test used a handful of short paths: a guard whose behaviour depends on a buffer threshold needs a test that crosses it. Refs: #698 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
f523fc535d |
fix(698): bind the base, constrain the bot exemption by content, re-derive unattributable successes
PR Gates / decisions lifecycle (pull_request) Successful in 24s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 27s
PR Gates / Docs update reminder (pull_request) Successful in 28s
Review verdict / Set review-verdict status (pull_request_target) Successful in 17s
PR Gates / Script tests (pytest) (pull_request) Successful in 1m1s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m9s
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
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 17m8s
review-verdict/h10 Review-verdict: BLOCKED @ f523fc5 (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 23m34s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
The `review-verdict/h10` exemption path decided from mutable or unattributed PR state, and a machine-written `success` was never revalidated. Three routes, one root cause, so one change. Route 1 (reproduced live as probe PR #703, closed unmerged): `/pulls/{n}/files` diffs against the PR's LIVE base, so retargeting moves the answer without moving the head sha. A PR opened into `main` and retargeted mid-run enumerated docs-only and was granted `h10=success` while its diff against `main` carried a C# file; retargeting back reclassified nothing. `scripts/pr-changed-files.sh` now takes the expected base branch as a REQUIRED 5th argument (optional would be a silent opt-out) and checks it before and after paging; the workflow passes it from the `pull_request_target` payload, which a retarget cannot rewrite, and `edited` is in `types:` so a retarget reclassifies. A pinned two-sha diff would close route 1 outright but Gitea 1.25.4 cannot serve one: `compare/{base}...{head}` returns no `files`, and a `--depth=1` fetch of the two shas has no merge base. Measured, not assumed. The residual window is stated in the code and the record rather than papered over. Route 2: `pull_request.user.login` is the PR's immutable CREATOR while its head is not, so pushing code onto an open Renovate branch kept the exemption. The bot exemption now also requires EVERY path to be a dependency manifest — a set measured across all 11 Renovate PRs this repo has had, not guessed. Route 3: the never-overwrite short-circuit exited on ANY `success`, so a forgery obtained once was inherited forever. It now fires only for a status positively identified as a human verdict (non-null `.creator.login` AND a `Review-verdict:` description — measured: user-posted statuses carry a creator, Actions-posted ones carry null). Written in the positive direction so an unrecognised shape is re-derived rather than trusted. The two exemptions are composed, not chained: as an `elif` chain a Renovate docs-only PR lost the docs-only exemption. Caught before commit and pinned by a test. Tests: 17 new cases in scripts/tests/test_pr_changed_files.py, each verified by mutating the clause it covers (8 mutations, 8 kills). Both records trimmed under the 60-line prose ceiling so the corpus tail-boundary check stays calibrated. Does NOT close the class: anyone who can POST a status directly can still impersonate a verdict — that is #697, deliberately left open. Refs: #698 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0c492defac |
Merge pull request 'fix(672): trigger the verdict gate on pull_request_target scoped to main' (#699) from fix/672-review-verdict-head-resolution into main
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 + UI contracts) (push) Successful in 16m19s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 20m21s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 23m5s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9m39s
|
||
|
|
4e2ea61674 |
Merge pull request 'fix(691): guard the nullable SongMetadata.Artists/AlbumArtists at their read sites' (#700) from fix/691-song-artists-null-guard into main
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 17s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 31s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 33s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
036bcfc5a0 |
Merge pull request 'fix(671): resolve rerun-collection selections through one shared include chain' (#692) from fix/671-rerun-collection-selection into main
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 + UI contracts) (push) Successful in 16s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 27s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 28s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m13s
|
||
|
|
d4ea1584c0 |
Merge pull request 'fix(668): reach accented facet values via a registered Unicode fold on SQLite' (#687) from fix/668-accented-facet-values into main
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 + UI contracts) (push) Successful in 33s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 34s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m17s
|
||
|
|
aa1f504e02 |
Merge pull request 'fix(684): key the pageSize guard registry on identity, not source position' (#686) from fix/pagesize-guard-line-churn into main
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 35s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 35s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m6s
|
||
|
|
ac0f65c743 |
Merge pull request 'docs(649): narrow the base-ref headline to what the checkout actually binds' (#683) from docs/649-narrow-base-ref-headline into main
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 + UI contracts) (push) Successful in 16s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 47s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 1m4s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9s
|
||
|
|
aeff810cad |
Merge pull request 'test(649): cover the review-verdict status read and the bot-path guards' (#673) from test/649-workflow-body-coverage into main
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 1m41s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
|
||
|
|
cb7da865b6 |
Merge pull request 'docs: permit subagents explicitly, and make claiming an issue a check rather than a label' (#682) from docs/claim-protocol-and-subagents into main
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 29s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 41s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 43s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 11s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
|
||
|
|
1d76a088c6 |
Merge pull request 'feat(578): artist typeahead covers music-video and song credits; album_artist stops 404ing' (#676) from feat/578-artist-typeahead-source into main
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 5m58s
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 19m9s
Build ErsatzTV Image / Build & test (.NET) (push) Failing after 3m39s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been skipped
|
||
|
|
d751f5e01d |
Merge pull request 'fix(650): two at-cap list truncations, and a completeness guard that keys on the defect' (#675) from fix/650-at-cap-truncation into main
Build ErsatzTV Image / Functional E2E (curl + UI 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
|
||
|
|
31f2a927a2 |
Merge pull request 'feat(651): library-browse pickers resolve by search, not a 100-row window' (#678) from feat/651-searchable-pickers into main
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 16s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 32s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 32s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 12m22s
Build CI Toolchain Image / Build & push CI image (push) Successful in 1m44s
Dependency vulnerability scan / NuGet vulnerable packages (push) Successful in 47s
|
||
|
|
8de02d5bde |
Merge pull request 'fix(649): point the ENFORCED review-verdict gate at the shared PR-file enumeration' (#666) from fix/649-enforced-verdict-guard into main
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 16m56s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 17m36s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 22m9s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 14m40s
Renovate / Renovate (push) Successful in 5m16s
|
||
|
|
8dcd4f3602 |
Merge pull request 'fix(632): bind a review verdict to its BASE branch, not only to its head sha' (#667) from fix/632-verdict-base-ref into main
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 18s
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 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 36s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
8103e34fff |
Merge pull request 'fix(648): an explicit jq version contract + one shared PR-file enumeration' (#658) from fix/648-649-jq-gates into main
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 8m41s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 16m49s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 18m37s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m11s
|
||
|
|
256cb0221b |
Merge pull request 'docs(ersatztv skill): record the #510 no-logo-no-bug policy and deco seeding recipe' (#659) from docs/510-skill-logo-bug-policy into main
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 15s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 29s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 30s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 19s
|
||
|
|
3684fd7ef6 |
Merge pull request 'docs(505): retire the stale "do NOT set QSV on jazz" rule in the ersatztv skill' (#657) from docs/505-skill-qsv-stale into main
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 13s
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 + UI contracts) (push) Successful in 24s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 27s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 15s
|
||
|
|
e4c0db7702 |
Merge pull request 'fix(510): one watermark resolver for all four attachment points' (#655) from fix/510-watermark-resolution-policy into main
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 8m28s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Failing after 16m31s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
|
||
|
|
c0376dcbce |
Merge pull request 'fix(644): stop seven SPA list loads truncating silently — one shared pager, bounded media pickers' (#656) from fix/644-spa-paging into main
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 + UI contracts) (push) Has been cancelled
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
|
||
|
|
6dbc072837 |
Merge pull request 'fix(505): tonemap QSV HDR through OpenCL — vpp_qsv=tonemap is a silent no-op' (#654) from fix/505-qsv-native-decode-tonemap into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 14s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 12s
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
|
||
|
|
34591c3ef6 |
Merge pull request 'fix(620): signal corpus size per RECORD; the aggregate becomes an untresholded trend' (#642) from fix/620-corpus-budget into main
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 16s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 28s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 31s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m25s
|
||
|
|
59558e134f |
Merge pull request 'fix(631): run scripts/tests in CI as its own job, not inside the flake-covered decisions-guard' (#637) from fix/631-script-tests-ci into main
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 20s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 35s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m51s
|
||
|
|
eb339084f9 |
Merge pull request 'fix(621): make an unparseable decision record loud instead of silently invisible' (#641) from fix/621-record-parse-guard into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 9m2s
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 16m33s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 18m7s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m57s
|
||
|
|
4fd806bebf |
Merge pull request 'fix(633): document the 0-based paging contract on the OpenAPI parameters' (#646) from fix/633-openapi-paging-descriptions into main
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 + UI 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
|
||
|
|
5f3623b321 |
Merge pull request 'fix(634): page the rerun-collection picker to completeness' (#645) from fix/634-rerun-picker-paging into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 12s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 14s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 33s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
caf3ca72c1 |
Merge pull request 'fix(629): close six false-opens in the H10 verdict grammar, and give it tests' (#636) from fix/629-verdict-classifier-falseopens into main
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 6m44s
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 + UI contracts) (push) Successful in 17m56s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 24m11s
Build ErsatzTV Image / Build & push image (amd64) (push) Failing after 13m7s
|
||
|
|
262262856f |
Merge pull request 'fix(617): make the cross-repo skills real symlinks and reconcile the ersatztv skill' (#639) from fix/617-skill-symlinks into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 14s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 14s
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
|
||
|
|
f394d6ce83 |
Merge pull request 'fix(616): paging is 0-based — correct the MCP contract, fix a live 1-based SPA caller, un-cap two MCP tools' (#635) from fix/616-paging-traps into main
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 8m37s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 15m32s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 18m12s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 17m49s
|
||
|
|
98f9e6ec34 |
Merge pull request 'fix(622): bind H10 merge consent to the reviewed sha via a required commit status' (#630) from feat/622-verdict-status-check into main
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 16m35s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 16m40s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 22m55s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
e03c36e371 |
Merge pull request 'fix(491): unique index on LibraryFolder(LibraryPathId, PathHash) + tolerate concurrent insert' (#613) from fix/491-libraryfolder-unique-index into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 11s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 12s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 11s
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) Successful in 4m25s
|
||
|
|
8e84191a03 |
Merge pull request 'feat(610): split the decision corpus into one YAML-frontmatter file per record' (#619) from feat/610-decisions-one-file-per-record into main
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 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 34s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 32s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m23s
|
||
|
|
798ecd1f53 |
Merge pull request 'fix(609): the decisions rationale-edit marker is a git trailer, not a bare substring' (#618) from fix/609-decisions-edit-token into main
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 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 34s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 34s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m32s
|
||
|
|
54ed75624a |
Merge pull request 'fix(496): per-library server identity for music videos — itemId diff + soft trash' (#607) from fix/496-musicvideo-identity into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 31s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 32s
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 + UI contracts) (push) Successful in 26s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 16m15s
|
||
|
|
eb4de0cc2b |
Merge pull request 'feat(484): suppress the media-server sweep on projection failures; reject the ratio threshold' (#612) from feat/484-scanner-guard-threshold into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 11s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 12s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 14s
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) Successful in 4m25s
|
||
|
|
fd70e6eb4f |
Merge pull request 'fix(503): map WatermarkLocation.MiddleCenter to a centered overlay position' (#611) from fix/503-watermark-middlecenter into main
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 7m56s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 17m30s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 17m6s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
c3beee1629 |
Merge pull request 'feat(603): adopt OKF's optional stale-after and Sources decision-record metadata' (#605) from worktree-603-decisions-stale-after-sources into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 14s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 18s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 12s
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
|
||
|
|
abeef63f05 |
Merge pull request 'feat(445,533): headless Playwright UI-E2E flows + fix e2e-local readiness probe' (#591) from feat/445-533-ui-e2e into main
Build CI Toolchain Image / Build & push CI image (push) Successful in 27s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 18m39s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 23m6s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 24m56s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 21m43s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been cancelled
|
||
|
|
e87285c33d |
Merge pull request 'fix(460): write null LastScan on disable-sync instead of the MinValue sentinel' (#601) from fix/460-lastscan-null into main
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 8m1s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 16m23s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 18m54s
Build ErsatzTV Image / Build & push image (amd64) (push) Failing after 6m0s
|
||
|
|
67e53b1304 |
Merge pull request 'chore(586,594,485): PID-scoped E2E cleanup, ci-image-pin length guard, .gitignore core fix' (#598) from chore/586-594-485-hygiene into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 8m11s
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
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
|
||
|
|
6f2898d7a9 |
Merge pull request 'fix(500): dedup incoming metadata collections so a duplicate name inserts once' (#602) from fix/500-distinct-metadata into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 26s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 32s
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 26s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
0952078c2b |
Merge pull request 'chore(docs): trim derivable content from CLAUDE.md, lazy-load the task-completion protocol' (#588) from chore/claudemd-trim-lazy-skill into main
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 42s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 41s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 42s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 15s
|
||
|
|
b7d9e0ecb9 |
Merge pull request 'docs(592): record that a skipped CI context is not red' (#593) from chore/skipped-not-red into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 15s
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 13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 26s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9s
|
||
|
|
bcff7c686a |
Merge pull request 'feat(440): per-source weight steppers + exclude/add-untagged in the Auto-Tune DetailPanel' (#589) from feat/440-autotune-weights into main
Build ErsatzTV Image / Build & test (.NET) (push) Has started running
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 / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
|
||
|
|
8664220aa5 |
Merge pull request 'chore(583): make per-agent model routing a hard constraint + PreToolUse gate' (#585) from chore/agent-model-routing into main
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 6m2s
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 / Build & test (.NET) (push) Has been cancelled
|
||
|
|
fa789bc06f |
Merge pull request 'feat(436): arbitrary-depth rule-builder group nesting' (#584) from feat/436-deeper-nesting into main
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
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
|
||
|
|
be1070de51 |
Merge pull request 'feat(437): inline RuleBuilder smart-query authoring in Channel Builder' (#579) from feat/437-rulebuilder-channelbuilder into main
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 15m56s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 16m3s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 20m47s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 11m29s
|
||
|
|
aca70b8398 |
Merge pull request 'feat(438,435,434): RuleBuilder validation, relative-date operators, DB-sourced facet typeahead' (#577) from feat/rulebuilder-bundle into main
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 33s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 34s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 12m5s
Merge PR #577 (feat/rulebuilder-bundle): RuleBuilder validation (#438), relative-date operators (#435), DB-sourced facet typeahead (#434) |
||
|
|
41291b3686 |
Merge pull request #573 (feat/392): per-schedule clock-boundary padding toggle + 60-min increment
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 32s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 33s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m40s
|
||
|
|
5a7a4ed7e0 |
Merge pull request 'fix(570): On Now/Next overlay YAML renders (font_family + format_datetime)' (#571) from fix/74-overlay-render into main
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 15s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 28s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 29s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9m39s
Merge pull request '#571 fix(570): On Now/Next overlay YAML renders (font_family + format_datetime)' (#571) from fix/74-overlay-render into main fixes #570 |
||
|
|
7080f63ebe |
Merge pull request 'feat(74): per-channel On Now/Next transient overlay' (#569) from feat/74-on-now-next-overlay into main
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 15s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 28s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 29s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m45s
Merge pull request '#569 feat(74): per-channel On Now/Next transient overlay' (#569) from feat/74-on-now-next-overlay into main fixes #74 |
||
|
|
d759a9fc83 |
Merge pull request 'refactor(395): dedup Scripted≡YAML enumerator construction into ContentEnumeratorBuilder' (#566) from issue-395-dedup-enumerator into main
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 31s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 31s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 32s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 9m37s
|
||
|
|
5c20a98468 |
Merge pull request 'test(381): Sequential (YAML) playout golden; document Scripted deferral' (#564) from feat/381-scheduler-goldens into main
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 5m47s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 18m56s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 19m8s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m14s
|
||
|
|
04ca7ae981 |
Merge pull request 'feat(297): add channelId to PlayoutListItemResponseModel; SPA reset keys directly' (#562) from issue-297-playout-channelid into main
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) Has started running
Build ErsatzTV Image / Build & push image (amd64) (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
|
||
|
|
5c73c7a4bd |
Merge pull request 'fix(248): focus-trap the shared modal overlay so Tab can't escape a dialog' (#561) from issue-248-overlay-focus-trap into main
Build ErsatzTV Image / Build & test (.NET) (push) Has started running
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has started running
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
|
||
|
|
1681ae4e60 |
Merge pull request 'fix(552): mint a short-lived JWT so the SPA reaches /iptv/* under JWT auth' (#560) from feat/552-spa-iptv-jwt into main
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 7m44s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 16m4s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 20m12s
Build ErsatzTV Image / Build & push image (amd64) (push) Has started running
|
||
|
|
d49d078264 |
Merge pull request 'test(512): flush LibrariesScreen scan-poll chain deterministically instead of waitFor timeouts' (#558) from issue-512-deterministic-libraries-test into main
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 8m1s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 15m37s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 19m18s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m45s
|
||
|
|
869253cd83 |
Merge pull request 'fix(553): exclude bot-authored issues from the queue selector' (#557) from issue-553-selector-bot-exclude into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 13s
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 32s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 34s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
|
||
|
|
732322dc84 |
Merge pull request 'feat(60): in-browser channel preview on the channels list' (#551) from feat/60-channel-preview into main
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 6m11s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 14m0s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 20m8s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 15m24s
|