-
Notifications
You must be signed in to change notification settings - Fork 1
staged: worktree-20260606-211401 -> staged-e90a943c6116-1780846417 #700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -231,6 +231,42 @@ print('failed' if fail else ('passed' if ok else 'not_found')) | |
| " 2>/dev/null | ||
| } | ||
|
|
||
| # ── A3b self-merge guard — SHARED decision (bug 374f) ───────────────────────── | ||
| # rc_a3b_should_exclude <sha> <mcs_match> | ||
| # | ||
| # A3b excludes a covering MERGED PR from providing review provenance for <sha> when | ||
| # that PR's merge_commit_sha == <sha> — but ONLY for a GENUINE merge node. A3b was | ||
| # written for merge-commit semantics: a >=2-parent merge node whose combined diff the | ||
| # sub-PR review never saw cannot be self-proven by its producing PR. After cca8 DD1 | ||
| # (rebase-not-merge) GitHub sets a rebase/squash-merged PR's merge_commit_sha to the | ||
| # rebased 1-parent TIP — a real commit patch-identical to reviewed sub-PR content | ||
| # (under merge-to-main, always the version-bump tip). Excluding THAT wrongly marks it | ||
| # UNREVIEWED and wedged every promotion under enforce (bug 374f). So: exclude ONLY when | ||
| # <sha> is NOT a proven 1-parent commit. A proven 1-parent rebase/squash tip keeps its | ||
| # covering evidence; the caller's G3 still re-verifies the review actually passed, so | ||
| # this cannot launder. | ||
| # | ||
| # DIVERGENCE-PROOF: this is the SINGLE source of the A3b decision. BOTH Goal-1 | ||
| # covering-PR filters route through it — rc_sha_is_reviewed (below) and the G3 routine | ||
| # in verify-session-provenance.sh (which sources this lib). Do not re-inline the guard | ||
| # in either caller; that is exactly the twin-divergence hazard bug 374f closed. | ||
| # | ||
| # Parent count is local git topology (authoritative offline; no API/rate-limit cost, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DSO llm-review — finding 2/5[important] Posted by dso_ci_review.runner; resolve this comment when addressed. |
||
| # consistent with rc_diff_is_*). FAIL-CLOSED: only an EXACTLY-1-parent result keeps the | ||
| # evidence; >=2 parents (true merge), 0 parents (root / shallow-clone boundary where a | ||
| # real merge can report 0), or empty output (commit absent) all EXCLUDE — preserving the | ||
| # pre-374f exclusion rather than loosening the guarantee. | ||
| # | ||
| # args: <sha> <mcs_match: 1 if covering PR's merge_commit_sha == sha, else 0> | ||
| # exit: 0 = EXCLUDE this covering PR ; 1 = KEEP it | ||
| rc_a3b_should_exclude() { | ||
| local _sha="${1:-}" _mcs_match="${2:-0}" _pc | ||
| [[ "$_mcs_match" == "1" ]] || return 1 # not a self-merge match -> keep | ||
| _pc="$(git rev-list --parents -n1 "$_sha" 2>/dev/null | awk 'NR==1{print NF-1}')" | ||
| [[ "$_pc" == "1" ]] && return 1 # exactly 1 parent (rebase/squash tip) -> keep | ||
| return 0 # >=2 / 0 / unknown -> exclude (fail-closed) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DSO llm-review — finding 1/5[critical] Posted by dso_ci_review.runner; resolve this comment when addressed. |
||
| } | ||
|
|
||
| rc_sha_is_reviewed() { | ||
| local repo="$1" sha="$2" pr_under_review="${3:-0}" | ||
| local pulls_json covering check_json verdict cov_pr cov_head | ||
|
|
@@ -263,27 +299,42 @@ for pr in prs: | |
| # A1 self-exclusion: the PR under review cannot provide its own provenance. | ||
| if pur > 0 and pr.get('number') == pur: | ||
| continue | ||
| # A3b self-merge guard only. The blanket A3a (head == sha_u) is intentionally | ||
| # A3b self-merge guard. The blanket A3a (head == sha_u) is intentionally | ||
| # NOT applied: a DIFFERENT merged sub-PR whose head IS sha_under_review is the | ||
| # VALID covering evidence (the common case — a sub-PR's own head commit). | ||
| # Excluding it would return false-UNREVIEWED for every sub-PR head SHA and, | ||
| # in enforce mode, block every legitimate staged->main merge. G3 below | ||
| # independently re-verifies the covering PR's review check actually PASSED, so | ||
| # keeping it cannot launder. (Mirrors the W4 fix in verify-session-provenance.sh.) | ||
| if pr.get('merge_commit_sha') == sha_u: | ||
| continue | ||
| # keeping it cannot launder. | ||
| # | ||
| # A3b itself (bug 374f) is NOT decided in Python: GitHub sets a rebase/squash- | ||
| # merged PR's merge_commit_sha to the rebased 1-parent TIP (under merge-to-main, | ||
| # the version-bump tip), so an unconditional merge_commit_sha==sha exclusion here | ||
| # wrongly marks that tip UNREVIEWED and wedges every promotion under enforce. We | ||
| # only emit a per-PR mcs_match flag; the bash caller routes it through the SHARED | ||
| # rc_a3b_should_exclude (single source of truth, also used by the G3 routine in | ||
| # verify-session-provenance.sh), which excludes only genuine >=2-parent merge | ||
| # nodes and fails closed on unknown topology. G3 still re-verifies the review. | ||
| mcs_match = 1 if pr.get('merge_commit_sha') == sha_u else 0 | ||
| # NOTE: merged_by is intentionally NOT read here — the /commits/{sha}/pulls list | ||
| # representation does not include it (null). The identity-exemption check (ADR-0022) | ||
| # fetches merged_by from the single-PR GET, on the bypass path only. | ||
| if head: | ||
| print(f\"{pr.get('number','')}\t{head}\") | ||
| print(f\"{pr.get('number','')}\t{head}\t{mcs_match}\") | ||
| " 2>/dev/null)" | ||
| local _filter_rc=$? | ||
| [[ $_filter_rc -eq 3 ]] && return 2 # parse error -> fail closed | ||
| [[ -z "$covering" ]] && return 1 # no covering merged PR -> not reviewed | ||
|
|
||
| while IFS=$'\t' read -r cov_pr cov_head; do | ||
| while IFS=$'\t' read -r cov_pr cov_head cov_mcs_match; do | ||
| [[ -z "$cov_head" ]] && continue | ||
| # A3b (narrowed, bug 374f): exclude this covering PR only if its merge_commit_sha | ||
| # == the SHA under review AND that SHA is a genuine merge node. Shared decision — | ||
| # see rc_a3b_should_exclude (single source of truth; the twin in | ||
| # verify-session-provenance.sh calls the same function). | ||
| if rc_a3b_should_exclude "$sha" "$cov_mcs_match"; then | ||
| continue | ||
| fi | ||
| check_json="$(_rc_gh_with_backoff api "repos/${repo}/commits/${cov_head}/check-runs")" || return 2 | ||
| verdict="$(printf '%s' "$check_json" | rc_review_check_verdict)" | ||
| case "$verdict" in | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -605,13 +605,21 @@ for pr in pr_list: | |
| # CANNOT launder, because G3 below independently verifies that each kept | ||
| # covering PR review check actually PASSED. Do NOT re-add the blanket A3a. | ||
| # A3b: self-merge guard (a SHA cannot be provenanced by the merge commit it | ||
| # itself produced). | ||
| if pr.get('merge_commit_sha') == sha_under_review: | ||
| continue | ||
| # itself produced) — but NOT decided here (bug 374f). GitHub sets a rebase/ | ||
| # squash-merged PR's merge_commit_sha to the rebased 1-parent TIP (under | ||
| # merge-to-main, the version-bump tip); an unconditional exclusion here would | ||
| # falsely drop that reviewed tip and force a needless re-review. Emit a per-PR | ||
| # mcs_match flag instead; the bash loop routes it through the SHARED | ||
| # rc_a3b_should_exclude (single source of truth, also used by | ||
| # review-coverage-lib.sh::rc_sha_is_reviewed) which excludes only genuine | ||
| # >=2-parent merge nodes, fail-closed on unknown topology. G3 below still | ||
| # verifies each kept covering PR's review actually passed, so this cannot launder. | ||
| # NOTE: merged_by is NOT read here — the /commits/{sha}/pulls list representation | ||
| # omits it (null). The identity check (ADR-0022) fetches merged_by from the | ||
| # single-PR GET, on the bypass path only. | ||
| print(number if number is not None else '') | ||
| if number is not None: | ||
| mcs_match = 1 if pr.get('merge_commit_sha') == sha_under_review else 0 | ||
| print(f'{number}\t{mcs_match}') | ||
| " 2>/dev/null)" || covering_prs="" | ||
|
|
||
| # G3 fix: verify that each covering PR's review-sub-pr check actually | ||
|
|
@@ -620,8 +628,15 @@ for pr in pr_list: | |
| # failed review would incorrectly count as "covered." | ||
| _verified_covering=0 | ||
| if [[ -n "$covering_prs" ]]; then | ||
| while IFS= read -r _cov_pr; do | ||
| while IFS=$'\t' read -r _cov_pr _cov_mcs_match; do | ||
| [[ -z "$_cov_pr" ]] && continue | ||
| # A3b (bug 374f, SHARED): exclude a covering PR whose merge_commit_sha == | ||
| # this SHA only when the SHA is a genuine merge node. rc_a3b_should_exclude | ||
| # (review-coverage-lib.sh) is the single source of truth — identical to | ||
| # rc_sha_is_reviewed's A3b so the two Goal-1 filters cannot diverge. | ||
| if rc_a3b_should_exclude "$sha" "${_cov_mcs_match:-0}"; then | ||
| continue | ||
| fi | ||
|
Comment on lines
+631
to
+639
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (( _api_call_count >= GH_BUDGET )); then | ||
| if (( _budget_exhausted == 0 )); then | ||
| echo "BUDGET_EXHAUSTED during G3 review-check verification" >&2 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| #!/usr/bin/env bash | ||
| # tests/scripts/test-rc-a3b-should-exclude.sh — bug 374f unit test | ||
| # | ||
| # Drives the PRODUCTION rc_a3b_should_exclude (review-coverage-lib.sh) over REAL git | ||
| # fixtures. This is the SHARED A3b self-merge decision: BOTH Goal-1 covering-PR filters | ||
| # route through it (review-coverage-lib.sh::rc_sha_is_reviewed AND the G3 routine in | ||
| # verify-session-provenance.sh), so the A3b semantics cannot diverge between them. | ||
| # | ||
| # SEMANTICS (preserve exactly): | ||
| # - mcs_match==0 (covering PR's merge_commit_sha != sha) -> KEEP (1) | ||
| # - mcs_match==1 AND sha is a 1-parent commit (rebase/squash tip) -> KEEP (1) | ||
| # (patch-identical to reviewed content; G3 still verifies the review passed) | ||
| # - mcs_match==1 AND sha is a >=2-parent genuine merge node -> EXCLUDE (0) | ||
| # - mcs_match==1 AND topology UNKNOWN (absent / 0-parent boundary) -> EXCLUDE (0) | ||
| # FAIL-CLOSED: only a PROVEN 1-parent tip is kept. | ||
| # | ||
| # This is the divergence-guard the panel (epic 588e) required: the single shared | ||
| # decision is unit-tested here; rc_sha_is_reviewed's T14/T15 and the vsp suites | ||
| # exercise it through each caller. | ||
|
|
||
| set -uo pipefail | ||
| export GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null GIT_TERMINAL_PROMPT=0 | ||
| REPO_ROOT="$(git rev-parse --show-toplevel)" | ||
| LIB="$REPO_ROOT/plugins/dso/scripts/lib/review-coverage-lib.sh" # shim-exempt: test sources the lib under test | ||
|
|
||
| PASS=0; FAIL=0 | ||
| _pass() { echo "PASS: $1"; PASS=$((PASS+1)); } | ||
| _fail() { echo "FAIL: $1 ($2)"; FAIL=$((FAIL+1)); } | ||
|
|
||
| _W="$(mktemp -d "${TMPDIR:-/tmp}/dso-a3b.XXXXXX")"; trap 'rm -rf "$_W"' EXIT | ||
| R="$_W/repo"; mkdir -p "$R" | ||
| ( | ||
| cd "$R" || exit 1 | ||
| git init -q -b main | ||
| git config user.email t@e.st; git config user.name t; git config commit.gpgsign false | ||
| echo base > README.md; git add README.md; git commit -q -m base | ||
|
|
||
| # A 1-parent commit (rebase/squash tip class). | ||
| echo tip > tip.txt; git add tip.txt; git commit -q -m "1-parent tip" | ||
| git rev-parse HEAD > "$_W/ONE" | ||
|
|
||
| # A genuine 2-parent merge node. | ||
| git checkout -q -b side HEAD~1 | ||
| echo s > side.txt; git add side.txt; git commit -q -m side | ||
| git checkout -q main | ||
| git merge -q --no-ff -m "2-parent merge node" side | ||
| git rev-parse HEAD > "$_W/TWO" | ||
| ) || { echo "FIXTURE SETUP FAILED"; exit 1; } | ||
|
|
||
| # shellcheck source=/dev/null | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DSO llm-review — finding 3/5[important] Posted by dso_ci_review.runner; resolve this comment when addressed. |
||
| source "$LIB" | ||
|
|
||
| _verdict() { ( cd "$R" && rc_a3b_should_exclude "$1" "$2" >/dev/null 2>&1; echo $? ); } | ||
| _assert() { if [[ "$2" == "$3" ]]; then _pass "$1"; else _fail "$1" "rc=$2 want $3"; fi; } | ||
|
|
||
| ONE="$(cat "$_W/ONE")"; TWO="$(cat "$_W/TWO")" | ||
|
|
||
| # mcs_match==0 -> always KEEP (1), regardless of topology. | ||
| _assert "no-merge-match (1-parent) -> keep" "$(_verdict "$ONE" 0)" 1 | ||
| _assert "no-merge-match (2-parent) -> keep" "$(_verdict "$TWO" 0)" 1 | ||
| # mcs_match==1 -> decide on parent count. | ||
| _assert "self-merge match + 1-parent tip -> keep" "$(_verdict "$ONE" 1)" 1 | ||
| _assert "self-merge match + 2-parent node -> EXCLUDE" "$(_verdict "$TWO" 1)" 0 | ||
| # Fail-closed: unknown topology (absent SHA reports empty parent count) -> EXCLUDE. | ||
| _assert "self-merge match + absent SHA -> EXCLUDE (fail closed)" \ | ||
| "$(_verdict "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" 1)" 0 | ||
| # Default mcs_match (missing arg -> 0) -> keep. | ||
| _assert "missing mcs_match arg defaults to keep" "$( cd "$R" && rc_a3b_should_exclude "$ONE" >/dev/null 2>&1; echo $? )" 1 | ||
|
|
||
| echo "" | ||
| echo "=== test-rc-a3b-should-exclude.sh: PASS=$PASS FAIL=$FAIL ===" | ||
| [[ $FAIL -eq 0 ]] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DSO llm-review — finding 5/5
[important]
.github/workflows/review-gate.yml:13.github/workflows/review-gate.yml:82(design)Posted by dso_ci_review.runner; resolve this comment when addressed.