This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 646e8bece7a Limit PR review confirmation to six independent
assessments (#40305)
646e8bece7a is described below
commit 646e8bece7ae60dd99087a506fc08d1b423c7181
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Oct 20 23:23:11 2026 +0800
Limit PR review confirmation to six independent assessments (#40305)
---
.codex/harness/agents/cases.toml | 18 +++++++++---------
.../skills/review-pr/references/review-coordination.md | 12 ++++++++----
.codex/skills/review-pr/scripts/review_ledger.py | 10 +++++++---
.codex/skills/review-pr/tests/test_review_ledger.py | 9 +++++++++
4 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/.codex/harness/agents/cases.toml b/.codex/harness/agents/cases.toml
index 2b078b27e63..e4bc2c042f3 100644
--- a/.codex/harness/agents/cases.toml
+++ b/.codex/harness/agents/cases.toml
@@ -4461,7 +4461,7 @@ required_summary_terms = ["A=review-both-results",
"B=adjudicate-and-obtain-seco
forbidden_summary_terms = ["A=finish-immediately",
"B=accept-matching-mergeable", "C=same-issue-set", "D=different-issue-sets",
"E=invent-code-defect", "E=mergeable"]
critical = true
policy_binding_profile = "review-pr"
-policy_assertions = [{source = "review-pr-coordination", statements = ["The
coordinator must substantively review both assessments and their supporting
evidence even when their verdicts and issue lists already match.", "Recheck
each claim's full path, strongest counter-evidence, necessity, scope and
decision classification, and check the pair for duplicated issues, omitted
historical candidates and unsupported acceptance conclusions.", "Normalize
issues by root cause, trigger and indepen [...]
+policy_assertions = [{source = "review-pr-coordination", statements = ["The
coordinator must substantively review both assessments and their supporting
evidence even when their verdicts and issue lists already match.", "Recheck
each claim's full path, strongest counter-evidence, necessity, scope and
decision classification, and check the pair for duplicated issues, omitted
historical candidates and unsupported acceptance conclusions.", "Normalize
issues by root cause, trigger and indepen [...]
[[cases]]
id = "review_pair_preserves_historical_candidate_dispositions"
@@ -4486,22 +4486,22 @@ policy_assertions = [{source =
"review-pr-coordination", statements = ["Preserve
[[cases]]
id = "review_pair_limit_is_not_missing_evidence"
group = "review-pr independent review coordination"
-description = "Continues confirmation beyond two rounds without misclassifying
disagreement as unavailable evidence."
+description = "Allows a third pair but stops at six assessments without
misclassifying exhaustion as unavailable evidence."
phase = "read-only review-convergence termination assessment"
ordinary_loop = false
profile = "review-pr"
semantic_policy_assertions = true
-prompt = "Answer this self-contained read-only policy question using only the
supplied facts and bound rules; do not inspect files, run commands, edit
anything or produce a Formal Review report. A: four complete independent
reviews on one unchanged basis form two pairs. The first pair disagrees and the
second pair still disagrees after substantive result review. No decisive fact
is unavailable, and further isolated reviews are available. Choose
A=continue-third-round or A=stop-not-conver [...]
+prompt = "Answer this self-contained read-only policy question using only the
supplied facts and bound rules; do not inspect files, run commands, edit
anything or produce a Formal Review report. A: four complete independent
reviews on one unchanged basis form two pairs. The first pair disagrees and the
second pair still disagrees after substantive result review. No decisive fact
is unavailable, and further isolated reviews are available. Choose
A=continue-third-round or A=stop-not-conver [...]
decision = "proceed"
required_actions = []
allowed_actions = []
forbidden_actions = ["inspect_local", "edit_code", "edit_non_code",
"run_local_checks", "run_pre_handoff_review", "propose_commit_message",
"mutate_git", "mutate_remote"]
required_reasons = ["read_only_request"]
-required_summary_terms = ["A=continue-third-round",
"A_verdict=no-formal-result", "B=adjudicate-and-continue",
"C=review-incomplete", "D=report-missing-scope"]
-forbidden_summary_terms = ["A=stop-not-converged",
"A_verdict=review-incomplete", "B=review-incomplete", "C=mergeable",
"D=claim-completed-dual-review"]
+required_summary_terms = ["A=continue-third-round",
"A_verdict=no-formal-result", "B=adjudicate-and-continue",
"C=review-incomplete", "D=report-missing-scope", "E=stop-not-converged",
"E_verdict=no-formal-result", "F=complete", "G=exclude-coordinator-and-checks"]
+forbidden_summary_terms = ["A=stop-not-converged",
"A_verdict=review-incomplete", "B=review-incomplete", "C=mergeable",
"D=claim-completed-dual-review", "E=continue-fourth-round",
"E_verdict=review-incomplete", "F=stop-not-converged",
"G=count-coordinator-and-checks"]
critical = true
policy_binding_profile = "review-pr"
-policy_assertions = [{source = "review-pr-coordination", statements = ["Do not
select an arbitrary matching pair across rounds or impose an unagreed round or
time limit.", "Otherwise verify the differences, record their evidence-based
dispositions without changing the original assessments, retain the updated
current adjudication as the next comparison baseline and start a fresh round.",
"If a concrete failure prevents continuing confirmation, report `Review Status:
Not Converged`, that r [...]
+policy_assertions = [{source = "review-pr-coordination", statements = ["Permit
at most three pairs and six complete independent assessments for one unchanged
review basis.", "Coordinator result reviews, evidence checks and verification
reports do not count toward this limit.", "Do not select an arbitrary matching
pair across rounds or impose an unagreed round or time limit.", "Do not extend
the six-assessment limit without explicit user authorization.", "Otherwise
verify the differences, [...]
[[cases]]
id = "review_confirmation_requires_fresh_adjacent_agreement"
@@ -4511,17 +4511,17 @@ phase = "read-only cross-round confirmation assessment"
ordinary_loop = false
profile = "review-pr"
semantic_policy_assertions = true
-prompt = "Answer this self-contained read-only policy question using only the
supplied facts and bound rules; do not inspect files, run commands, edit
anything or produce a Formal Review report. The following states are
independent reviews on unchanged established bases, with complete supported
evidence and historical dispositions except for the stated differences. A: the
first fresh pair and its substantive adjudication all agree on Mergeable.
Choose A=continue or A=complete. B: the sec [...]
+prompt = "Answer this self-contained read-only policy question using only the
supplied facts and bound rules; do not inspect files, run commands, edit
anything or produce a Formal Review report. The following states are
independent reviews on unchanged established bases, with complete supported
evidence and historical dispositions except for the stated differences. A: the
first fresh pair and its substantive adjudication all agree on Mergeable.
Choose A=continue or A=complete. B: the sec [...]
decision = "proceed"
required_actions = []
allowed_actions = []
forbidden_actions = ["inspect_local", "edit_code", "edit_non_code",
"run_local_checks", "run_pre_handoff_review", "propose_commit_message",
"mutate_git", "mutate_remote"]
required_reasons = ["read_only_request"]
-required_summary_terms = ["A=continue", "B=complete", "C=continue",
"D=continue", "E=continue", "F=complete"]
+required_summary_terms = ["A=continue", "B=complete", "C=continue",
"D=stop-not-converged", "E=continue", "F=complete"]
forbidden_summary_terms = ["A=complete", "B=continue",
"C=complete-on-stable-adjudication", "D=accept-nonadjacent-match",
"E=accept-matching-counts", "F=continue-on-metadata-change"]
critical = true
policy_binding_profile = "review-pr"
-policy_assertions = [{source = "review-pr-coordination", statements = ["If no
previous adjudication exists on this basis, retain this first adjudication as
the comparison baseline and start a fresh round; the first round cannot
complete confirmation.", "Compare the previous and current complete
adjudications, including every canonical issue's identity, status and
classification, evidence gaps, discussion conditions, result and feedback
mode.", "Compare unchanged decisions semantically; r [...]
+policy_assertions = [{source = "review-pr-coordination", statements = ["Permit
at most three pairs and six complete independent assessments for one unchanged
review basis.", "If the third pair does not satisfy confirmation or a concrete
failure prevents continuing confirmation, report `Review Status: Not
Converged`, that reason, the confirmed facts and unresolved differences without
a formal `Review Result` line or a mergeability conclusion.", "If no previous
adjudication exists on this [...]
[[cases]]
id = "review_confirmation_restarts_after_basis_change"
diff --git a/.codex/skills/review-pr/references/review-coordination.md
b/.codex/skills/review-pr/references/review-coordination.md
index 5152447c4ba..5f80066800c 100644
--- a/.codex/skills/review-pr/references/review-coordination.md
+++ b/.codex/skills/review-pr/references/review-coordination.md
@@ -47,6 +47,9 @@ The coordinator's result review is focused verification of
the reports and their
## Cross-Round Confirmation
+Permit at most three pairs and six complete independent assessments for one
unchanged review basis.
+Coordinator result reviews, evidence checks and verification reports do not
count toward this limit.
+
Before changing an overall conclusion, compare the prior and current effective
candidates, requirement sources and versions, applicable exceptions, review
focus, evidence identities and finding sets; candidate-type or Git revision
labels and a different previous verdict do not establish a changed basis.
A changed effective candidate, requirement, rule version or outcome-sensitive
external fact invalidates the affected prior assessments; never combine results
from different bases to pass this gate.
Start fresh confirmation on the changed basis while retaining the original
task baseline, attributed scope, historical candidates and original assessments.
@@ -59,13 +62,14 @@ Only consecutive rounds on the current basis count toward
its confirmation; earl
Compare unchanged decisions semantically; reviewer identities, member
mappings, file hashes, evidence wording and report ordering do not establish a
changed conclusion.
5. Confirm only when the fresh pair's normalized complete assessments agree
with each other, the previous adjudication and the current adjudication, the
supporting evidence and counter-evidence are sufficient, and no unresolved
issue can change the conclusion.
An evidenced need for a maintainer decision may be a confirmed `Needs
Discussion` condition; it does not establish a code defect.
-6. Otherwise verify the differences, record their evidence-based dispositions
without changing the original assessments, retain the updated current
adjudication as the next comparison baseline and start a fresh round.
+6. Otherwise verify the differences, record their evidence-based dispositions
without changing the original assessments, retain the updated current
adjudication as the next comparison baseline and start a fresh round only while
fewer than three pairs have completed on this basis.
-Any substantive issue, classification, disposition, evidence-gap or readiness
change requires a subsequent fresh pair.
+Any substantive issue, classification, disposition, evidence-gap or readiness
change requires a subsequent fresh pair within this limit; if none remains, do
not confirm the changed conclusion.
The coordinator must retain and compare the prior adjudication even though the
fresh reviewers must not receive it.
Do not select an arbitrary matching pair across rounds or impose an unagreed
round or time limit.
-If a concrete failure prevents continuing confirmation, report `Review Status:
Not Converged`, that reason, the confirmed facts and unresolved differences
without a formal `Review Result` line or a mergeability conclusion.
-Disagreement or an unavailable isolation mechanism does not satisfy the Review
Incomplete Proof Gate.
+Do not extend the six-assessment limit without explicit user authorization.
+If the third pair does not satisfy confirmation or a concrete failure prevents
continuing confirmation, report `Review Status: Not Converged`, that reason,
the confirmed facts and unresolved differences without a formal `Review Result`
line or a mergeability conclusion.
+Disagreement, exhausted review attempts or an unavailable isolation mechanism
do not satisfy the Review Incomplete Proof Gate.
When authoritative scope cannot be established, preserve the Review Incomplete
Proof Gate's missing-scope evidence route and state explicitly that complete
independent code reviews could not start.
That proven scope failure may return the existing `Review Incomplete` report
without a session, but must not claim completed dual coverage or a mergeability
conclusion.
diff --git a/.codex/skills/review-pr/scripts/review_ledger.py
b/.codex/skills/review-pr/scripts/review_ledger.py
index a273ed9e9d2..941933711de 100755
--- a/.codex/skills/review-pr/scripts/review_ledger.py
+++ b/.codex/skills/review-pr/scripts/review_ledger.py
@@ -837,7 +837,10 @@ def validate_session(session: Any) -> list[str]:
source_versions = {}
source_versions.update(pair_versions)
previous_identity = identity
- if len(session["rounds"]) - current_start < 2:
+ current_pairs = len(session["rounds"]) - current_start
+ if current_pairs > 3:
+ errors.append("The current review basis exceeds six independent
original assessments")
+ if current_pairs < 2:
errors.append("The current review basis requires at least two
consecutive independent pairs")
for index, record in enumerate(records):
ledger = record["ledger"]
@@ -902,8 +905,9 @@ def validate_session(session: Any) -> list[str]:
frozenset((each["id"], each["status"],
each["classification"]) for each in final_groups)))
if any(each["status"] == "candidate" for each in final_groups):
errors.append("Result-review candidates remain unresolved")
- if len(session["rounds"]) - current_start >= 2 and assessments[-2] !=
assessments[-1]:
- errors.append("The latest complete adjudication differs from the
previous round; obtain a fresh independent pair")
+ if current_pairs >= 2 and assessments[-2] != assessments[-1]:
+ action = "obtain a fresh independent pair" if current_pairs < 3 else
"stop and report Review Status: Not Converged"
+ errors.append("The latest complete adjudication differs from the
previous round; " + action)
if (session["result"], session["feedback_mode"]) != assessments[-1][:2]:
errors.append("The final decision contradicts the latest complete
adjudication")
expected = (session["result"], session["feedback_mode"], confirmed, gaps)
diff --git a/.codex/skills/review-pr/tests/test_review_ledger.py
b/.codex/skills/review-pr/tests/test_review_ledger.py
index f1c43fd1a0a..2868e593c89 100644
--- a/.codex/skills/review-pr/tests/test_review_ledger.py
+++ b/.codex/skills/review-pr/tests/test_review_ledger.py
@@ -750,6 +750,15 @@ class ReviewLedgerTest(unittest.TestCase):
"evidence":
actual["rounds"][-1]["report_reviews"][0]["evidence"]})
self.assertEqual([], ledger.validate_session(actual))
+ def test_session_rejects_more_than_three_complete_pairs(self):
+ actual = self.create_session([[]] * 8)
+ self.assertIn("The current review basis exceeds six independent
original assessments", ledger.validate_session(actual))
+
+ def test_session_stops_after_third_unconfirmed_pair(self):
+ actual = self.create_session([[("F1", "confirmed")]] * 6)
+ actual["rounds"][-1]["findings"][0]["classification"] = "performance"
+ self.assertIn("The latest complete adjudication differs from the
previous round; stop and report Review Status: Not Converged",
ledger.validate_session(actual))
+
def test_session_requires_confirmation_after_first_round(self):
actual = self.create_session([[], []])
actual.update({"reviews": actual["reviews"][:2], "rounds":
actual["rounds"][:1]})