Files
ersatztv/scripts
timothyandClaude Opus 5 fe578c5864
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 20s
PR Gates / Docs update reminder (pull_request) Successful in 24s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 26s
PR Gates / decisions lifecycle (pull_request) Successful in 31s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
review-verdict/h10 Awaiting review verdict for fe578c5
Review verdict / Set review-verdict status (pull_request_target) Successful in 14s
PR Gates / Script tests (pytest) (pull_request) Successful in 4m8s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m38s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m19s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 4s
feat(778): name the check-and-use race, and verify the protection the merge gate rests on
#773 §3 Family D is the one class its taxonomy had no bucket for: a check and the
action it authorizes are separated in time over state that can change in between,
with nothing pinning a version (#536, #622, #632, #706, #707).

The repo had already solved this twice without noticing it was one problem — a
compare-exchange claim in-process (ffmpeg.work-ahead-slot-atomic) and RFC 7232
If-Match across /api/v1 (concurrency.ifmatch-rfc7232) — and then solved it a third
time from scratch for the tooling at #706/#707. Hence a class-level record rather
than a fourth per-instance one.

What the enumeration actually found, which none of the five records predicted:
the merge-consent hook's scheduled-auto-merge path is safe only because
`review-verdict/h10` is a REQUIRED status check on main. That is branch-protection
CONFIG, it lives outside this repo, nothing compared the two, and the hook asserted
it in a comment AND in the grant reason a human reads. Switch the context off and
every word of that sentence is false while the hook keeps printing it and keeps
auto-granting. The hook now reads the branch protection and treats it as three
outcomes: present proceeds, unreadable asks, absent denies.

Two defects were caught by the new checks themselves rather than by review:
- the population test found .gitea/workflows/dependency-scan.yml absent from the
  first draft of the inventory (a sixth workflow the recon slice never listed);
- self-review found the guard denying with a confident wrong reason when jq errors
  one level down on a malformed contexts member, so the word is now matched
  exhaustively rather than compared against "yes". Same swallow that survived the
  first fix in the #632 base-change guard.

Detector D has no plausible linter, so the detector is detector A applied to an
enumerated inventory: docs/remote-state-inventory.md classifies every in-scope
executable, and scripts/tests/test_remote_state_inventory.py derives the population
from the filesystem and asserts set equality both ways.

Deferred with reasons stated in the inventory: select-queue.sh (advisory, authorizes
no write), ci-detect-already-validated.sh (skip elides re-validation only, the image
still builds), review-verdict.yml's status POST (Gitea offers no conditional write;
already fenced by #706's retarget counter).

Mutation proofs witnessed for both new guards, clause-level, not whole-file.

fixes #778

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 12:57:04 +02:00
..
2024-01-15 10:29:07 -06:00
2024-01-16 13:28:46 -06:00