chore(process): #303 H10 — review-verdict merge-gate (latest commit must be reviewed) #306

Merged
timothy merged 4 commits from ci/303-h10-review-verdict-gate into main 2026-07-12 19:32:00 +02:00
4 Commits
Author SHA1 Message Date
timothyandClaude Opus 4.8 938733c3d0 fix(process): #303 H10 — anchor is_pos to the leading marker (monotonic hardening)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 12s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 13s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 12s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m28s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 9m27s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Final re-review returned SHIP-IT with one contrived, pre-existing residual: a
line starting `Review-verdict: BLOCKED …` that ALSO contains a second literal
`review-verdict: mergeable` substring later on the same line read as positive.
Anchor the is_pos check to line-start so only the line's OWN leading verdict
word counts. Safe-by-construction: anchoring a positive matcher can only REDUCE
the allow-surface, so it cannot introduce a false-open (the dangerous
direction); the 21-case regression confirms no false-deny (all still
allow/deny/ask as before) + a new B6 case for this exact vector. No further
review round needed — the change is monotonic. shellcheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:14:37 +02:00
timothyandClaude Opus 4.8 ff3df39c43 fix(process): #303 H10 — anchor verdict marker to line-start (close self-reference false-open) [decisions-edit]
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 12s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 12s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 14s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m59s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m13s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Second adversarial re-review (of the fix commit itself — dogfooding H10) found
a remaining false-open: the `review-verdict:` marker was matched anywhere on a
line, so a comment merely QUOTING the positive template — an instruction
("please post: Review-verdict: MERGEABLE @ <head>"), a blocking comment
explaining how to clear itself, or the gate's OWN suggestion text echoed into a
comment — was classified as a real head verdict and self-approved the merge.

Fix: anchor the marker to line-start (`^[[:space:]]*review-verdict:`). A real
verdict line starts with the marker; quoted/instructional uses have text before
it. Also drops the dead `nosha` var (SC2034).

Finding 2 (a BLOCKED mis-anchored to an OLDER sha doesn't retract a
MERGEABLE@head) is deliberately NOT "fixed": staleness is symmetric — a
pre-fix BLOCKED@oldsha must not block forever after the fix changes the sha and
earns a fresh MERGEABLE@head. To retract, re-review head and post BLOCKED@head.
Documented in decisions.md.

Pipe-tested 21 cases (5 new: instructional-quote, self-reference reason-text,
line-start-in-multiline, leading-whitespace, blocking-quotes-template), all
deny/ask/allow correct. bash -n + shellcheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:11:05 +02:00
timothyandClaude Opus 4.8 f87a2092c4 fix(process): #303 H10 — anchor sha match to the @<sha> field; retraction-wins [decisions-edit]
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 14s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m13s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Adversarial review found false-opens in the first cut:
- `grep -F "$short"` was an unanchored substring test: a MERGEABLE verdict for
  a DIFFERENT/older commit was accepted whenever the head 7-prefix appeared
  anywhere on the line (inside a longer sha, or an unrelated commit URL). Now
  each verdict line's `@ <sha>` token is extracted and matched to head by git
  short-sha prefix semantics (head begins with token, token >=7 chars).
- No retraction semantics: a later `BLOCKED @ head` didn't override an earlier
  `MERGEABLE @ head`. Now a negative verdict on head wins -> deny.
- A 7-digit build number falsely tripped the "references an older commit" deny;
  the `@`-anchored parse fixes it -> a marker with no @sha now asks, not denies.

Also documents the issue-comment scope (gate reads issues/{pr}/comments, not
Gitea formal-review bodies). Pipe-tested: 16 cases incl. 4 adversarial
false-open reproductions, all now deny/ask. bash -n + shellcheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:01:51 +02:00
timothyandClaude Opus 4.8 9fd8f40541 chore(process): #303 H10 — review-verdict merge-gate (latest commit must be reviewed)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 13s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 13s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 14s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m4s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 9m43s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Folds condition (c) into pretooluse-merge-consent.sh (H6): a PR merge is
allowed only when a `Review-verdict:` comment references the PR's CURRENT
head sha — proving the latest commit was reviewed, not a stale earlier diff
(mechanizes the ersatztv#242 "re-review the fix commit" lesson).

Graceful adoption mirrors H6's Done-when tiering:
- positive verdict @ head        -> allow
- verdict @ older sha (stale)    -> deny  (#242 failure mode)
- head verdict negative          -> deny
- marker with no sha / none yet  -> ask
- comments unfetchable           -> ask

Reuses H6's PR fetch, docs-only exemption, and Gitea-auth-from-env (one hook,
no detection drift — per the #303 methodology review). Pipe-tested 12 cases.

Docs: decisions.md (new H10 entry + TOC), CLAUDE.md Task Completion Protocol.

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