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 84723bf7dee Improve PR review evidence reuse and ledger cleanup
(#40183)
84723bf7dee is described below
commit 84723bf7dee2d3acaddb721f4e92d5794952f5c2
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Oct 13 22:14:19 2026 +0800
Improve PR review evidence reuse and ledger cleanup (#40183)
---
.codex/harness/agents/cases.toml | 40 ++++++++
.codex/skills/review-pr/SKILL.md | 9 ++
.codex/skills/review-pr/scripts/review_ledger.py | 36 +++++--
.../skills/review-pr/tests/test_review_ledger.py | 112 +++++++++++++++++++++
4 files changed, 187 insertions(+), 10 deletions(-)
diff --git a/.codex/harness/agents/cases.toml b/.codex/harness/agents/cases.toml
index 8a14e86d4f1..1ea20f8c1b7 100644
--- a/.codex/harness/agents/cases.toml
+++ b/.codex/harness/agents/cases.toml
@@ -3595,3 +3595,43 @@ forbidden_summary_terms =
["origin=introduced-by-latest-commits", "origin=expose
critical = true
policy_binding_profile = "review-pr"
policy_assertions = [{source = "review-pr", statements = ["For a proven
previous-review miss, contradictory assessments on an unchanged basis, a
triggered high-risk review criterion, or an explicit user request for
independent review, obtain an independent read-only assessment through this
workflow and the Completion Gate using the current basis and complete effective
candidate without the previous verdict or an expected finding count.", "Never
use a previous Formal Review result as\nevi [...]
+
+[[cases]]
+id = "review_ledger_reuses_facts_without_inheriting_completion"
+group = "review-pr evidence reuse"
+description = "Shares current facts across discovery lenses while requiring
fresh review and reacquisition of changed evidence."
+phase = "read-only evidence-reuse 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: the current review ledger
contains raw evidence whose source versions, supporting inputs and applicable
coverage are proved current. The root-cause lens used that material, and the
blast-radius and tests-runtime lenses still need to assess the complete
candidate. Decide whether they may share [...]
+decision = "proceed"
+required_actions = []
+allowed_actions = []
+forbidden_actions = ["inspect_local", "edit_code", "edit_non_code",
"run_local_checks", "measure_performance", "run_pre_handoff_review",
"propose_commit_message", "mutate_git", "mutate_remote"]
+required_reasons = ["read_only_request"]
+required_summary_terms = ["A=share-material", "B=fresh-review",
"C=reacquire-evidence", "D=pending-and-candidate"]
+forbidden_summary_terms = ["A=reacquire-material", "B=inherit-completion",
"C=reuse-old-fact", "D=reviewed-and-confirmed"]
+critical = true
+policy_binding_profile = "review-pr"
+policy_assertions = [{source = "review-pr", statements = ["Reuse only facts
and verification results whose current-candidate validity is established; do
not inherit reviewed-file statuses, discovery passes, proof conclusions, or
convergence results.", "Before repeating evidence acquisition, consult the
current ledger's sources, block coverage, candidate findings and verification
material, and reuse facts only while their supporting inputs and applicable
coverage remain valid.", "All thre [...]
+
+[[cases]]
+id = "review_temporary_ledger_cleanup_preserves_report_and_scope"
+group = "review-pr temporary ledger lifecycle"
+description = "Cleans the exact current-review resources on terminal paths
while preserving external sources, the report and the original error."
+phase = "read-only review-cleanup 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, execute cleanup or
produce a Formal Review report. For every state the current review's temporary
ledger path was returned by initialization and recorded, resource ownership is
established and the exact cleanup route is available. A, B and C are
independent completed reviews whose self-contained reports already contain all
required evidence; their results ar [...]
+decision = "proceed"
+required_actions = []
+allowed_actions = []
+forbidden_actions = ["inspect_local", "delete_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=cleanup", "B=cleanup", "C=cleanup", "D=preserve",
"E=report-cleanup-failure", "assessment=unchanged",
"F=attempt-cleanup-and-preserve-error"]
+forbidden_summary_terms = ["A=retain", "B=retain", "C=retain", "D=delete",
"E=claim-cleanup-success", "assessment=change-verdict",
"F=skip-cleanup-or-hide-error"]
+critical = true
+policy_binding_profile = "review-pr"
+policy_assertions = [{source = "review-pr", statements = ["Use the existing
private system temporary directory and record the exact ledger path returned by
initialization for this review.", "Keep ledger data private and remove only the
exact current-review ledger.", "Before returning a completed review result,
form a self-contained report and automatically run `scripts/review_ledger.py
cleanup --ledger <recorded-ledger>` for the recorded current-review instance,
including Mergeable, Not [...]
diff --git a/.codex/skills/review-pr/SKILL.md b/.codex/skills/review-pr/SKILL.md
index 37ec75e104e..6a5324f6f08 100644
--- a/.codex/skills/review-pr/SKILL.md
+++ b/.codex/skills/review-pr/SKILL.md
@@ -176,8 +176,11 @@ Apply this workflow to the canonical review basis without
letting output mode or
Start every Formal Review round with fresh coverage of the complete effective
candidate and its affected behavior and contracts, preserving the original task
baseline and attributed scope.
Reuse only facts and verification results whose current-candidate validity is
established; do not inherit reviewed-file statuses, discovery passes, proof
conclusions, or convergence results.
+Before repeating evidence acquisition, consult the current ledger's sources,
block coverage, candidate findings and verification material, and reuse facts
only while their supporting inputs and applicable coverage remain valid.
+All three discovery lenses may share the same current source material, but
each must still cover the complete candidate and sharing material does not
replace the convergence pass.
For a proven previous-review miss, contradictory assessments on an unchanged
basis, a triggered high-risk review criterion, or an explicit user request for
independent review, obtain an independent read-only assessment through this
workflow and the Completion Gate using the current basis and complete effective
candidate without the previous verdict or an expected finding count.
+Give the independent reviewer the current requirements and their provenance,
complete candidate inventory and relevant raw evidence rather than the author's
full session history.
1. Complete `Repository Code Policy References`, then establish the
authoritative effective-candidate scope and applicable requirements.
2. Complete the Problem and Project Commitment Gate and establish the accepted
behavior boundary.
@@ -207,13 +210,19 @@ Apply the Completion Gate to every Formal Review and to a
discussion reply that
- Use `scripts/build_review_inventory.py --format json` when local refs are
available; its Markdown is only a bounded summary.
- Use `scripts/review_ledger.py` for multi-file, high-risk, or omission-prone
review; it accounts for review state but does not judge correctness.
- Initialize a new ledger for each round that requires one, from the full
current inventory with pending file statuses and no inherited review passes.
+- Use the existing private system temporary directory and record the exact
ledger path returned by initialization for this review.
- Initialize with `--review-basis <JSON>` containing the selected focus and
readable sources identified by role and origin, so the ledger binds their
actual content versions to the effective candidate, original baseline and
authoritative files.
- Record each substantive changed block's behavior, applicable risk axes and
requirement origins, strongest counter-evidence and current source anchors with
`mark-file --coverage <JSON>`, and attach finding anchors with `add-finding
--anchors <JSON>`.
+- Record partial coverage with pending files and keep unproved findings as
candidates; recording evidence does not establish a completed review.
- Rebuild ledgers with an older schema or stale inputs without inheriting
their completion state.
- Validate the current basis and coverage before selecting a result; a passing
ledger proves mechanical coverage and evidence freshness, while the reviewer
must still establish semantic proof under the existing gates.
- For a standalone local candidate with index or working-tree changes, provide
the same exact task-path file to both scripts with `--candidate-files <path>`.
The scripts resolve those paths from the computed merge-base through the
working tree, include matching untracked files, and fail when a listed path is
unchanged.
- Mutate one ledger sequentially; do not run ledger commands concurrently.
- Keep ledger data private and remove only the exact current-review ledger.
+- Before returning a completed review result, form a self-contained report and
automatically run `scripts/review_ledger.py cleanup --ledger <recorded-ledger>`
for the recorded current-review instance, including Mergeable, Not Mergeable
and Review Incomplete results.
+- Before cleaning the ledger, remove only temporary input materials created
and explicitly recorded for this review, preserving declared sources owned by
the repository, the user or another review.
+- On a handled failure or cancellation, attempt the same cleanup for resources
whose ownership is established, preserve the original failure and report any
cleanup failure or remaining resources.
+- Keep the report independent of temporary files and report cleanup failures
without changing the review assessment.
Use these JSON shapes in local files passed to the arguments, replacing the
example values with current evidence and block IDs from the initialized ledger:
Sources use `rule`, `requirement` or `evidence` roles; `--anchors` takes an
anchor-array file shaped like `anchors` below.
diff --git a/.codex/skills/review-pr/scripts/review_ledger.py
b/.codex/skills/review-pr/scripts/review_ledger.py
index 913c70ba1cc..4d68a4069a1 100755
--- a/.codex/skills/review-pr/scripts/review_ledger.py
+++ b/.codex/skills/review-pr/scripts/review_ledger.py
@@ -26,7 +26,6 @@ import hashlib
import json
import os
import re
-import shutil
import stat
import subprocess
import sys
@@ -81,11 +80,12 @@ def resolve_ledger_file(value: str | Path) -> Path:
return result / LEDGER_FILE_NAME if result.is_dir() else result
-def ensure_safe_ledger_file(ledger_file: Path) -> None:
+def ensure_safe_ledger_file(ledger_file: Path) -> Path:
root = ledger_root().resolve()
target = ledger_file.resolve()
if LEDGER_FILE_NAME != target.name or root != target.parent.parent:
raise RuntimeError(f"Ledger is outside the private review ledger root:
{target}")
+ return target
def validate_schema(ledger: object) -> None:
@@ -163,15 +163,14 @@ def validate_schema(ledger: object) -> None:
def read_ledger(value: str | Path) -> dict[str, Any]:
- ledger_file = resolve_ledger_file(value)
- ensure_safe_ledger_file(ledger_file)
+ ledger_file = ensure_safe_ledger_file(resolve_ledger_file(value))
ledger = json.loads(ledger_file.read_text(encoding="utf-8"))
validate_schema(ledger)
return ledger
def write_ledger(ledger_file: Path, ledger: dict[str, Any]) -> None:
- ensure_safe_ledger_file(ledger_file)
+ ledger_file = ensure_safe_ledger_file(ledger_file)
ledger["updated_at"] = int(time.time())
temporary_file = ledger_file.with_suffix(".tmp")
temporary_file.write_text(json.dumps(ledger, indent=2, sort_keys=True) +
"\n", encoding="utf-8")
@@ -487,7 +486,14 @@ def cmd_init(args: argparse.Namespace) -> int:
"findings": [],
"passes": [],
}
- write_ledger(ledger_file, ledger)
+ try:
+ write_ledger(ledger_file, ledger)
+ except (OSError, RuntimeError):
+ try:
+ remove_ledger_dir(ledger_file)
+ except (OSError, RuntimeError) as ex:
+ print(f"error: Initialization cleanup failed; current-review
resources may remain at {ledger_dir}: {ex}", file=sys.stderr)
+ raise
print(f"ledger={ledger_file}")
print(f"files={len(changed_files)}")
return 0
@@ -751,12 +757,22 @@ def cmd_status(args: argparse.Namespace) -> int:
return 0
+def remove_ledger_dir(ledger_file: Path) -> None:
+ ledger_file = ensure_safe_ledger_file(ledger_file)
+ ledger_dir = ledger_file.parent
+ entries = list(ledger_dir.iterdir())
+ owned_names = {LEDGER_FILE_NAME, ledger_file.with_suffix(".tmp").name}
+ if any(each.name not in owned_names or each.is_symlink() or not
each.is_file() for each in entries):
+ raise RuntimeError("Ledger directory contains unowned resources;
cleanup refused")
+ for entry in entries:
+ entry.unlink()
+ ledger_dir.rmdir()
+
+
def cmd_cleanup(args: argparse.Namespace) -> int:
- ledger_file = resolve_ledger_file(args.ledger)
+ ledger_file = ensure_safe_ledger_file(resolve_ledger_file(args.ledger))
read_ledger(ledger_file)
- ledger_dir = ledger_file.parent
- ensure_safe_ledger_file(ledger_file)
- shutil.rmtree(ledger_dir)
+ remove_ledger_dir(ledger_file)
print("removed=1")
return 0
diff --git a/.codex/skills/review-pr/tests/test_review_ledger.py
b/.codex/skills/review-pr/tests/test_review_ledger.py
index 986431d3434..72594645100 100644
--- a/.codex/skills/review-pr/tests/test_review_ledger.py
+++ b/.codex/skills/review-pr/tests/test_review_ledger.py
@@ -230,6 +230,118 @@ class ReviewLedgerTest(unittest.TestCase):
with self.assertRaisesRegex(RuntimeError, "outside the private
review ledger root"):
ledger.ensure_safe_ledger_file(outside_file)
+ def test_file_alias_read_and_write_use_canonical_ledger(self):
+ actual = self.create_valid_ledger()
+ outside = self.private_root / "outside"
+ outside.mkdir()
+ alias = outside / "alias.json"
+ alias.symlink_to(self.ledger_file)
+ actual["review_revision"] += 1
+ ledger.write_ledger(alias, actual)
+ self.assertTrue(alias.is_symlink())
+ self.assertFalse(alias.with_suffix(".tmp").exists())
+ self.assertEqual(actual, ledger.read_ledger(alias))
+ self.assertEqual(actual, ledger.read_ledger(self.ledger_file))
+
+ def
test_cleanup_file_alias_preserves_external_and_sibling_directories(self):
+ actual = self.create_valid_ledger()
+ sibling = ledger.create_ledger_dir(self.repo, "sibling",
self.base_sha) / ledger.LEDGER_FILE_NAME
+ ledger.write_ledger(sibling, actual)
+ sibling_content = sibling.read_bytes()
+ outside = self.private_root / "outside"
+ outside.mkdir()
+ marker = outside / "keep.txt"
+ marker.write_text("Unrelated external resource.\n", encoding="utf-8")
+ alias = outside / "alias.json"
+ alias.symlink_to(self.ledger_file)
+ with redirect_stdout(StringIO()):
+ self.assertEqual(0,
ledger.cmd_cleanup(Namespace(ledger=str(alias))))
+ self.assertFalse(self.ledger_file.parent.exists())
+ self.assertTrue(alias.is_symlink())
+ self.assertEqual("Unrelated external resource.\n",
marker.read_text(encoding="utf-8"))
+ self.assertEqual(sibling_content, sibling.read_bytes())
+
+ def test_cleanup_rejects_ledger_outside_private_root(self):
+ actual = self.create_valid_ledger()
+ outside = self.private_root / "outside"
+ outside.mkdir()
+ outside_file = outside / ledger.LEDGER_FILE_NAME
+ outside_file.write_text(json.dumps(actual), encoding="utf-8")
+ content = outside_file.read_bytes()
+ with self.assertRaisesRegex(RuntimeError, "outside the private review
ledger root"):
+ ledger.cmd_cleanup(Namespace(ledger=str(outside_file)))
+ self.assertEqual(content, outside_file.read_bytes())
+ self.assertTrue(self.ledger_file.exists())
+
+ def test_cleanup_rejects_unowned_directory_contents(self):
+ self.create_valid_ledger()
+ unknown = self.ledger_file.parent / "coverage.json"
+ unknown.write_text("Unattributed temporary input.\n", encoding="utf-8")
+ content = self.ledger_file.read_bytes()
+ with self.assertRaisesRegex(RuntimeError, "unowned resources; cleanup
refused"):
+ ledger.cmd_cleanup(Namespace(ledger=str(self.ledger_file)))
+ self.assertEqual(content, self.ledger_file.read_bytes())
+ self.assertEqual("Unattributed temporary input.\n",
unknown.read_text(encoding="utf-8"))
+
+ def test_cleanup_preserves_invalid_ledger(self):
+ self.create_valid_ledger()
+ self.ledger_file.write_text("{}", encoding="utf-8")
+ with self.assertRaisesRegex(RuntimeError, "Unsupported or invalid
review coverage ledger"):
+ ledger.cmd_cleanup(Namespace(ledger=str(self.ledger_file)))
+ self.assertEqual("{}", self.ledger_file.read_text(encoding="utf-8"))
+
+ def test_cleanup_failure_is_reported(self):
+ self.create_valid_ledger()
+ content = self.ledger_file.read_bytes()
+ output, error = StringIO(), StringIO()
+ arguments = ["review_ledger.py", "cleanup", "--ledger",
str(self.ledger_file)]
+ with patch.object(sys, "argv", arguments), patch.object(Path,
"unlink", side_effect=PermissionError("cleanup denied")), \
+ redirect_stdout(output), redirect_stderr(error):
+ self.assertEqual(1, ledger.main())
+ self.assertEqual("", output.getvalue())
+ self.assertEqual("error: cleanup denied\n", error.getvalue())
+ self.assertEqual(content, self.ledger_file.read_bytes())
+
+ def test_init_write_failure_removes_only_new_directory(self):
+ self.create_valid_ledger()
+ sibling = self.ledger_file
+ content = sibling.read_bytes()
+ failure = OSError("initial write failed")
+
+ def fail_write(ledger_file, _):
+ ledger_file.with_suffix(".tmp").write_text("Partial initial
write.\n", encoding="utf-8")
+ raise failure
+
+ with patch.object(ledger, "write_ledger", side_effect=fail_write),
self.assertRaises(OSError) as caught:
+ self.initialize_ledger()
+ self.assertIs(failure, caught.exception)
+ self.assertEqual([sibling.parent],
list(ledger.ledger_root().iterdir()))
+ self.assertEqual(content, sibling.read_bytes())
+
+ def
test_init_cleanup_failure_preserves_original_error_and_reports_residuals(self):
+ failure = OSError("initial write failed")
+
+ def fail_write(ledger_file, _):
+ ledger_file.with_suffix(".tmp").write_text("Partial initial
write.\n", encoding="utf-8")
+ raise failure
+
+ error = StringIO()
+ with patch.object(ledger, "write_ledger", side_effect=fail_write),
patch.object(Path, "unlink", side_effect=PermissionError("cleanup denied")), \
+ redirect_stderr(error), self.assertRaises(OSError) as caught:
+ self.initialize_ledger()
+ self.assertIs(failure, caught.exception)
+ directories = list(ledger.ledger_root().iterdir())
+ self.assertEqual(1, len(directories))
+ self.assertEqual("Partial initial write.\n", (directories[0] /
"ledger.tmp").read_text(encoding="utf-8"))
+ self.assertEqual(f"error: Initialization cleanup failed;
current-review resources may remain at {directories[0]}: cleanup denied\n",
error.getvalue())
+
+ def test_init_write_failure_before_output_removes_new_directory(self):
+ failure = PermissionError("initial write denied")
+ with patch.object(ledger, "write_ledger", side_effect=failure),
self.assertRaises(PermissionError) as caught:
+ self.initialize_ledger()
+ self.assertIs(failure, caught.exception)
+ self.assertEqual([], list(ledger.ledger_root().iterdir()))
+
def test_old_ledger_version_requires_new_review(self):
actual = self.create_valid_ledger()
actual["version"] = 3