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 31aa4032958 Enforce formal review for code-writing tasks (#39838)
31aa4032958 is described below
commit 31aa4032958f50c61f50e48e49b4acfb0251f8ea
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Sep 14 00:30:37 2026 +0800
Enforce formal review for code-writing tasks (#39838)
---
.codex/config.toml | 11 +-
.codex/context/change-completion.md | 14 +-
.codex/harness/agents/cases.toml | 41 ++--
.codex/harness/agents/code_handoff_hook.py | 273 +++++++++++++++++++++---
.codex/harness/agents/run.py | 4 +-
.codex/harness/agents/test_code_handoff_hook.py | 200 +++++++++++++++--
.codex/harness/agents/test_run.py | 6 +-
AGENTS.md | 2 +-
8 files changed, 467 insertions(+), 84 deletions(-)
diff --git a/.codex/config.toml b/.codex/config.toml
index d8ddb264778..fbfe16e2634 100644
--- a/.codex/config.toml
+++ b/.codex/config.toml
@@ -13,8 +13,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+[[hooks.PreToolUse]]
+matcher = "^(Bash|exec_command|write_stdin)$"
+
+[[hooks.PreToolUse.hooks]]
+type = "command"
+command = '/usr/bin/python3 "$(git rev-parse
--show-toplevel)/.codex/harness/agents/code_handoff_hook.py"'
+command_windows = 'py -3 "$(git rev-parse
--show-toplevel)/.codex/harness/agents/code_handoff_hook.py"'
+timeout = 5
+
[[hooks.PostToolUse]]
-matcher = "^apply_patch$"
+matcher = "^(Bash|apply_patch|exec_command|write_stdin)$"
[[hooks.PostToolUse.hooks]]
type = "command"
diff --git a/.codex/context/change-completion.md
b/.codex/context/change-completion.md
index 932352c5120..10f8f0b3f9a 100644
--- a/.codex/context/change-completion.md
+++ b/.codex/context/change-completion.md
@@ -19,19 +19,21 @@
This file is the sole owner of completion-loop orchestration. Other policy
sources may route here or define their own implementation and verification
rules, but must not duplicate this sequence or its review selection.
-For an authorized change, build, implement, or fix request, excluding a
standalone restoration or rollback:
+For every authorized code-writing task, including a restoration or rollback
that changes production, test, script, build, generated, or behavior-affecting
configuration artifacts:
1. Perform the post-write task-delta audit required by `AGENTS.md` with the
read-only diff, surrounding context, and acceptance checklist. Confirm every
task-introduced hunk is necessary and allowlisted, prohibited paths have no
task delta, architecture changes were authorized, tests protect owned behavior,
and unattributed work remains untouched.
2. Apply every triggered coding-standard and simplification rule to the
effective task delta. Treat scripts, searches, formatters, compilation, tests,
benchmarks, and review tools as evidence rather than proof, and fix every safe
in-scope violation.
3. Run the applicable verification and non-regression checks. An invalidated,
unmatched, missing, or inconclusive required result keeps the task incomplete.
-4. Use bounded self-review for an internal local candidate when inspection
proves that its frozen owners and behavior are fully understood, module
dependencies and public or externally visible contracts are unchanged,
applicable verification is complete, and no Formal Review trigger below is
present. The candidate may span files or modules when they implement one
bounded behavior and verification covers every changed owner and affected
consumer. Review root-cause and fix mapping, affecte [...]
-5. Invoke `$review-pr` in Formal Review Mode when the user requests a PR,
mergeability, or formal review; the task targets or backs a PR; or the
candidate changes a public API, SPI, externally visible contract, module
dependency, security or concurrency behavior, or user-visible runtime
performance, or contains a contract-affecting deletion, irreversible action,
last-consumer removal, or unresolved evidence. An ordinary internal
implementation, build change, or private deletion uses boun [...]
-6. Fix every safe in-scope required finding, repeat the task-delta audit,
rerun invalidated checks, and repeat the applicable review. Stop at the
existing gate for a scope expansion, unresolved architecture choice, high-risk
action, `Review Incomplete`, or `Needs Discussion` result.
-7. Hand off a bounded-review candidate only after the review finds no required
issue. Include its concise completed review result in the final handoff. Hand
off a Formal Review candidate only after the latest complete report returns
`Review Result: Mergeable`, and include the complete Formal Review report in
the final handoff.
+4. Invoke `$review-pr` in Formal Review Mode for the complete task-owned
candidate. Use Code Correctness Review for a standalone local candidate unless
the user requests another focus. For a PR-backed candidate, apply the
public-head, remote-evidence, and mandatory style-verification gates; for a
standalone candidate, review only the original task baseline and attributed
task-owned delta.
+5. Hand off only when the latest complete Formal Review returns `Review
Result: Mergeable` and no later code-affecting write or new evidence
invalidates it. Include that complete passing Formal Review report unchanged in
the final handoff.
+6. When Formal Review returns `Not Mergeable` with a safe in-scope Change
Request, fix every required finding, repeat the task-delta audit, rerun
invalidated checks, and rerun Formal Review. Continue this loop until it
returns `Review Result: Mergeable`.
+7. A scope expansion, missing authority, unresolved architecture choice,
high-risk action, `Review Incomplete`, or `Needs Discussion` result keeps the
task incomplete. Yield to the user only for the exact decision, authority, or
unavailable evidence needed to continue; do not claim successful completion or
provide commit artifacts while the task remains incomplete.
8. After a code-writing task completes, provide a commit message without being
asked; this never authorizes Git mutation. Provide manual Git commands only
when the user requests them. Propose `git commit --dry-run --only` and `git
commit --only` for only task-owned files without unrelated hunks, list a
required `git add -- <new-task-paths>` first for untracked task files, and
never execute a Git write without exact current-task authorization.
When the delta audit, required current-state checks, and applicable review
pass and no later write or new evidence invalidates them, the loop is complete.
Do not repeat an unchanged check, audit, or review.
If a report or verdict is disproved, fix the highest-leverage rule, schema,
validator, prompt, or regression case before correcting the artifact, unless
the user explicitly requests a one-off correction.
-The final response must lead with the outcome and include changed files and
rationale, verification status, remaining risks, and the next action only when
one is still required. Every code-writing handoff must explicitly report the
completed code review result and review recommendations. Put a value on
separate `Review Result:`, `Blocking Issues:`, `Required Changes:`, and `Review
Recommendations:` lines so the project Stop hook can validate the handoff after
`apply_patch` changes a non- [...]
+The final response must lead with the outcome and include changed files and
rationale, verification status, remaining risks, and the next action only when
one is still required. Every successful code-writing handoff must include the
latest complete passing Formal Review as the exact fenced `markdown` artifact
required by `$review-pr`, with `### Result`, exactly one `Review Result:
Mergeable`, `### Evidence`, and `### Coverage`. Put required non-review handoff
details, including a non-emp [...]
+
+The project Stop hook validates this contract after supported write tools
change a non-prose repository artifact. Any later code-affecting write marks
the task pending again and requires a new passing Formal Review. When step 7
requires user input, include the complete non-passing Formal Review plus
separate `Task Status: Awaiting User` and non-empty `Required User Action:`
lines; the hook may yield that turn but must retain the pending state. Omit
`Commit Message:` until the task succeeds.
diff --git a/.codex/harness/agents/cases.toml b/.codex/harness/agents/cases.toml
index e8db3cc2d08..5ca1a23924e 100644
--- a/.codex/harness/agents/cases.toml
+++ b/.codex/harness/agents/cases.toml
@@ -1209,20 +1209,20 @@ critical = true
[[cases]]
id = "internal_review_matches_pr_correctness"
group = "coding / regular"
-description = "Uses bounded self-review for a proven private internal
policy-harness change that has no public or shared-boundary effect."
+description = "Requires review-pr Formal Review even for a proven private
internal policy-harness change."
phase = "ordinary completion loop"
ordinary_loop = true
profile = "code-write"
semantic_policy_assertions = true
-prompt = "An authorized local implementation changes a private method
signature and private constructor in this repository's internal Codex policy
harness. Inspection proves the changes stay inside one owner and cannot affect
supported product, build, public or shared module boundaries, or user-visible
runtime performance. Module dependencies and public or externally visible
contracts are unchanged, the frozen owners and affected consumers are fully
understood, and scoped verification an [...]
+prompt = "An authorized local implementation changes only a private method and
private constructor in this repository's internal Codex policy harness. The
task delta, scoped verification, and non-regression evidence are complete, and
no public or shared contract changes. No review has run. Complete the
policy-required review without editing, producing commit artifacts, changing
Git, or substituting a bounded self-review."
decision = "proceed"
-required_actions = ["run_bounded_adversarial_review"]
-allowed_actions = ["inspect_local", "run_bounded_adversarial_review"]
-forbidden_actions = ["edit_code", "edit_non_code", "run_pre_handoff_review",
"propose_commit_message", "mutate_git", "mutate_remote"]
-required_reasons = ["bounded_adversarial_review_required"]
-required_summary_terms = ["bounded"]
+required_actions = ["run_pre_handoff_review"]
+allowed_actions = ["inspect_local", "run_pre_handoff_review"]
+forbidden_actions = ["edit_code", "edit_non_code",
"run_bounded_adversarial_review", "propose_commit_message", "mutate_git",
"mutate_remote"]
+required_reasons = ["pre_handoff_review_required"]
+required_summary_terms = ["$review-pr", "Formal Review"]
policy_binding_profile = "code-write"
-policy_assertions = [{source = "change-completion", statements = ["Use bounded
self-review for an internal local candidate when inspection proves that its
frozen owners and behavior are fully understood, module dependencies and public
or externally visible contracts are unchanged, applicable verification is
complete, and no Formal Review trigger below is present.", "The candidate may
span files or modules when they implement one bounded behavior and verification
covers every changed owne [...]
+policy_assertions = [{source = "change-completion", statements = ["Invoke
`$review-pr` in Formal Review Mode for the complete task-owned candidate.",
"Use Code Correctness Review for a standalone local candidate unless the user
requests another focus.", "Hand off only when the latest complete Formal Review
returns `Review Result: Mergeable` and no later code-affecting write or new
evidence invalidates it."]}]
critical = true
[[cases]]
@@ -1862,7 +1862,7 @@ phase = "ordinary completion loop"
ordinary_loop = true
profile = "code-write"
semantic_policy_assertions = true
-prompt = "All authorized code changes and current-state checks are complete, a
full local candidate review found no required findings, and no later write or
new evidence invalidated them. Complete the task without repeating an unchanged
check, audit, or review. The user did not request a commit message or authorize
Git mutation."
+prompt = "All authorized code changes and current-state checks are complete,
the latest `$review-pr` Formal Review returned `Review Result: Mergeable`, and
no later write or new evidence invalidated it. Complete the task without
repeating an unchanged check, audit, or review. The user did not request a
commit message or authorize Git mutation."
decision = "proceed"
required_actions = ["propose_commit_message"]
allowed_actions = ["inspect_local", "propose_commit_message"]
@@ -1875,20 +1875,20 @@ critical = true
[[cases]]
id = "completed_bounded_review_is_reported"
group = "operations"
-description = "Reports the bounded code review result, blocker count, and
absence of recommendations in every routine code handoff."
+description = "Reports the complete passing Formal Review in every routine
code handoff."
phase = "completion output gate"
ordinary_loop = true
profile = "code-write"
semantic_policy_assertions = true
-prompt = "A routine authorized code task is complete. Its implementation,
applicable verification, and bounded pre-handoff self-review are finished; the
review found no required issues, and no Formal Review trigger applies. Deliver
the final handoff. A response that only says the implementation is complete,
tests passed, `Mergeable`, or gives a commit message is insufficient."
+prompt = "A routine authorized code task is complete. Its implementation and
applicable verification are finished, the latest `$review-pr` Formal Review
returned `Review Result: Mergeable`, and no later write occurred. Deliver the
final handoff. A bounded review summary, bare verdict, passing tests, or commit
message without the complete Formal Review is insufficient."
decision = "proceed"
required_actions = ["propose_commit_message"]
allowed_actions = ["propose_commit_message"]
forbidden_actions = ["edit_code", "edit_non_code"]
required_reasons = []
-required_summary_terms = ["Review Result:", "Blocking Issues: 0", "Required
Changes:", "Review Recommendations:", "No changes recommended", "Commit
Message:"]
+required_summary_terms = ["```markdown", "### Result", "Review Result:
Mergeable", "### Evidence", "### Coverage", "```text", "Commit Message:"]
policy_binding_profile = "code-write"
-policy_assertions = [{source = "change-completion", statements = ["Every
code-writing handoff must explicitly report the completed code review result
and review recommendations.", "Put a value on separate `Review Result:`,
`Blocking Issues:`, `Required Changes:`, and `Review Recommendations:` lines so
the project Stop hook can validate the handoff after `apply_patch` changes a
non-prose file.", "State the blocking issue count and required changes, and
explicitly state `No changes recomme [...]
+policy_assertions = [{source = "change-completion", statements = ["Every
successful code-writing handoff must include the latest complete passing Formal
Review as the exact fenced `markdown` artifact required by `$review-pr`, with
`### Result`, exactly one `Review Result: Mergeable`, `### Evidence`, and `###
Coverage`.", "Put required non-review handoff details, including a non-empty
`Commit Message:`, in a separate fenced text block so the Formal Review
artifact remains unchanged.", "Va [...]
critical = true
[[cases]]
@@ -2582,13 +2582,13 @@ critical = true
[[cases]]
id = "standalone_local_completion_invokes_review_pr"
-group = "coding / high risk"
-description = "Requires review-pr Formal Review for a standalone architecture
or public-contract change."
+group = "coding / regular"
+description = "Requires review-pr Formal Review for every standalone local
code change."
phase = "ordinary completion loop"
ordinary_loop = true
profile = "code-write"
semantic_policy_assertions = true
-prompt = "An authorized standalone local change modifies an SPI signature used
across modules. Its task delta, verification, and non-regression evidence are
complete, but no review has run. Invoke the required review and do not hand
off, propose commit artifacts, or change Git before that review returns
Mergeable."
+prompt = "An authorized standalone local code change is private, routine, and
limited to one owner. Its task delta, verification, and non-regression evidence
are complete, but no review has run. Invoke the required review and do not hand
off, propose commit artifacts, run a bounded substitute, or change Git before
that review returns Mergeable."
decision = "proceed"
required_actions = ["run_pre_handoff_review"]
allowed_actions = ["inspect_local", "run_pre_handoff_review"]
@@ -2596,7 +2596,7 @@ forbidden_actions = ["edit_code", "edit_non_code",
"run_bounded_adversarial_revi
required_reasons = ["pre_handoff_review_required"]
required_summary_terms = ["Formal Review", "Mergeable"]
policy_binding_profile = "code-write"
-policy_assertions = [{source = "change-completion", statements = ["Invoke
`$review-pr` in Formal Review Mode when the user requests a PR, mergeability,
or formal review; the task targets or backs a PR; or the candidate changes a
public API, SPI, externally visible contract, module dependency, security or
concurrency behavior, or user-visible runtime performance, or contains a
contract-affecting deletion, irreversible action, last-consumer removal, or
unresolved evidence. An ordinary inte [...]
+policy_assertions = [{source = "change-completion", statements = ["Invoke
`$review-pr` in Formal Review Mode for the complete task-owned candidate.",
"Use Code Correctness Review for a standalone local candidate unless the user
requests another focus.", "Hand off only when the latest complete Formal Review
returns `Review Result: Mergeable` and no later code-affecting write or new
evidence invalidates it."]}]
critical = true
[[cases]]
@@ -2615,7 +2615,7 @@ required_reasons = ["safe_in_scope_review_finding",
"pre_handoff_review_required
required_summary_terms = ["Spotless", "Checkstyle"]
required_summary_term_groups = [["Formal Review", "review"], ["Mergeable",
"passing"]]
policy_binding_profile = "code-write"
-policy_assertions = [{source = "change-completion", statements = ["Fix every
safe in-scope required finding, repeat the task-delta audit, rerun invalidated
checks, and repeat the applicable review.", "Hand off a Formal Review candidate
only after the latest complete report returns `Review Result: Mergeable`, and
include the complete Formal Review report in the final handoff."]}, {source =
"code-verification", statements = ["Capture high-volume output according to
`.codex/context/token-ef [...]
+policy_assertions = [{source = "change-completion", statements = ["When Formal
Review returns `Not Mergeable` with a safe in-scope Change Request, fix every
required finding, repeat the task-delta audit, rerun invalidated checks, and
rerun Formal Review.", "Continue this loop until it returns `Review Result:
Mergeable`."]}, {source = "code-verification", statements = ["Capture
high-volume output according to `.codex/context/token-efficiency.md`; report
commands, exit codes, and decisive [...]
critical = true
[[cases]]
@@ -2632,10 +2632,9 @@ required_actions = ["propose_commit_message"]
allowed_actions = ["inspect_local", "propose_commit_message"]
forbidden_actions = ["edit_code", "edit_non_code", "mutate_git",
"mutate_remote"]
required_reasons = ["review_passed", "git_read_only"]
-required_summary_terms = ["### Result", "Review Result: Mergeable", "No
changes recommended", "### Evidence", "### Coverage", "git commit --dry-run
--only", "git commit --only", "Foo.java", "FooTest.java"]
-required_summary_term_groups = [["Blocking Issues: 0", "Blocking issue count:
0"]]
+required_summary_terms = ["### Result", "Review Result: Mergeable", "###
Evidence", "### Coverage", "git commit --dry-run --only", "git commit --only",
"Foo.java", "FooTest.java"]
policy_binding_profile = "code-write"
-policy_assertions = [{source = "change-completion", statements = ["Hand off a
Formal Review candidate only after the latest complete report returns `Review
Result: Mergeable`, and include the complete Formal Review report in the final
handoff.", "Every code-writing handoff must explicitly report the completed
code review result and review recommendations.", "State the blocking issue
count and required changes, and explicitly state `No changes recommended` when
no findings exist.", "Provi [...]
+policy_assertions = [{source = "change-completion", statements = ["Hand off
only when the latest complete Formal Review returns `Review Result: Mergeable`
and no later code-affecting write or new evidence invalidates it.", "Include
that complete passing Formal Review report unchanged in the final handoff.",
"Every successful code-writing handoff must include the latest complete passing
Formal Review as the exact fenced `markdown` artifact required by `$review-pr`,
with `### Result`, exac [...]
critical = true
[[cases]]
diff --git a/.codex/harness/agents/code_handoff_hook.py
b/.codex/harness/agents/code_handoff_hook.py
index e60045844f0..45e0353e503 100644
--- a/.codex/harness/agents/code_handoff_hook.py
+++ b/.codex/harness/agents/code_handoff_hook.py
@@ -21,22 +21,31 @@ from __future__ import annotations
import hashlib
import json
+import os
from pathlib import Path
import re
+import subprocess
import sys
import tempfile
from typing import Any
PROSE_SUFFIXES = frozenset({".adoc", ".md", ".rst"})
PATCH_FILE_PATTERN = re.compile(r"^\*\*\* (?:Add|Delete|Update) File: (.+)$",
re.MULTILINE)
-FIELD_PATTERN =
r"^\s*(?:[-*]\s+)?(?:#{{1,6}}\s+)?(?:\*\*)?{label}:\s*(.*?)(?:\*\*)?\s*$"
-REQUIRED_FIELDS = ("Review Result", "Blocking Issues", "Required Changes",
"Review Recommendations")
-NO_CHANGES_RECOMMENDED = "No changes recommended"
+FIELD_PATTERN = r"^[ \t]*(?:[-*][ \t]+)?(?:#{{1,6}}[ \t]+)?(?:\*\*)?{label}:[
\t]*(.*?)(?:\*\*)?[ \t]*$"
+BOLD_FIELD_PATTERN = r"^[ \t]*(?:[-*][ \t]+)?\*\*{label}:[ \t]*(.*?)\*\*[
\t]*$"
+FORMAL_REVIEW_PATTERN = re.compile(r"^```markdown\s*$\n(.*?)^```\s*$",
re.IGNORECASE | re.MULTILINE | re.DOTALL)
+TEXT_BLOCK_PATTERN = re.compile(r"^```text\s*$\n(.*?)^```\s*$", re.IGNORECASE
| re.MULTILINE | re.DOTALL)
+SHELL_TOOL_NAMES = frozenset({"Bash", "exec_command", "write_stdin"})
+PASSING_RESULT = "Mergeable"
+PAUSED_RESULTS = frozenset({"Not Mergeable", "Review Incomplete"})
def process_event(event: dict[str, Any], state_directory: Path) -> dict[str,
str]:
"""Process one Codex hook event."""
event_name = event.get("hook_event_name")
+ if "PreToolUse" == event_name:
+ _record_pre_tool_state(event, state_directory)
+ return {}
if "PostToolUse" == event_name:
_record_implementation_change(event, state_directory)
return {}
@@ -45,20 +54,72 @@ def process_event(event: dict[str, Any], state_directory:
Path) -> dict[str, str
marker_path = _marker_path(event, state_directory)
if not marker_path.exists():
return {}
- failures = validate_handoff(event.get("last_assistant_message"))
- if failures:
- return {"decision": "block", "reason": _continuation_reason(failures)}
- marker_path.unlink()
- return {}
+ message = event.get("last_assistant_message")
+ passing_failures = validate_handoff(message)
+ if not passing_failures:
+ marker_path.unlink()
+ return {}
+ paused_failures = validate_paused_handoff(message)
+ if not paused_failures:
+ return {}
+ return {"decision": "block", "reason":
_continuation_reason(passing_failures, paused_failures)}
+
+
+def _record_pre_tool_state(event: dict[str, Any], state_directory: Path) ->
None:
+ if event.get("tool_name") not in SHELL_TOOL_NAMES:
+ return
+ snapshot_path = _snapshot_path(event, state_directory)
+ snapshot_path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
+ snapshot = _repository_snapshot(event)
+ snapshot_path.write_text(json.dumps(snapshot, sort_keys=True),
encoding="utf-8")
def _record_implementation_change(event: dict[str, Any], state_directory:
Path) -> None:
- if "apply_patch" != event.get("tool_name"):
+ tool_name = event.get("tool_name")
+ if tool_name in SHELL_TOOL_NAMES:
+ _record_shell_change(event, state_directory)
+ return
+ if "apply_patch" != tool_name:
return
tool_input = event.get("tool_input")
- patch = tool_input.get("command") if isinstance(tool_input, dict) else None
- if not isinstance(patch, str) or not _changes_implementation_file(patch):
+ patch = None
+ if isinstance(tool_input, dict):
+ patch = tool_input.get("command") or tool_input.get("patch")
+ if not isinstance(patch, str):
+ _mark_pending(event, state_directory)
+ return
+ if not _changes_implementation_file(patch):
+ return
+ _mark_pending(event, state_directory)
+
+
+def _record_shell_change(event: dict[str, Any], state_directory: Path) -> None:
+ snapshot_path = _snapshot_path(event, state_directory)
+ try:
+ before = json.loads(snapshot_path.read_text(encoding="utf-8"))
+ except (OSError, TypeError, ValueError, json.JSONDecodeError):
+ _mark_pending(event, state_directory)
return
+ finally:
+ snapshot_path.unlink(missing_ok=True)
+ after = _repository_snapshot(event)
+ if not isinstance(before, dict) or after is None or before.get("root") !=
after.get("root"):
+ _mark_pending(event, state_directory)
+ return
+ before_files = before.get("files", {})
+ after_files = after.get("files", {})
+ if not isinstance(before_files, dict) or not isinstance(after_files, dict):
+ _mark_pending(event, state_directory)
+ return
+ changed_paths = {
+ each for each in before_files.keys() | after_files.keys()
+ if before_files.get(each) != after_files.get(each)
+ }
+ if any(Path(each).suffix.lower() not in PROSE_SUFFIXES for each in
changed_paths):
+ _mark_pending(event, state_directory)
+
+
+def _mark_pending(event: dict[str, Any], state_directory: Path) -> None:
marker_path = _marker_path(event, state_directory)
marker_path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
marker_path.touch(exist_ok=True)
@@ -77,38 +138,190 @@ def _marker_path(event: dict[str, Any], state_directory:
Path) -> Path:
return state_directory / f"{marker_name}.pending"
+def _snapshot_path(event: dict[str, Any], state_directory: Path) -> Path:
+ tool_use_id = event.get("tool_use_id")
+ if not isinstance(tool_use_id, str) or not tool_use_id:
+ raise ValueError("Codex hook input is missing tool_use_id")
+ session_name = _marker_path(event, state_directory).stem
+ tool_name = hashlib.sha256(tool_use_id.encode("utf-8")).hexdigest()
+ return state_directory / f"{session_name}.{tool_name}.before.json"
+
+
+def _repository_snapshot(event: dict[str, Any]) -> dict[str, Any] | None:
+ cwd = event.get("cwd")
+ tool_input = event.get("tool_input")
+ if not isinstance(cwd, str) or not cwd:
+ cwd = tool_input.get("workdir") if isinstance(tool_input, dict) else
None
+ if not isinstance(cwd, str) or not cwd:
+ cwd = os.getcwd()
+ root_result = _run_git(Path(cwd), "rev-parse", "--show-toplevel")
+ if root_result is None:
+ return None
+ root = Path(root_result.decode("utf-8", errors="surrogateescape").strip())
+ status = _run_git(root, "status", "--porcelain=v1", "-z",
"--untracked-files=all")
+ if status is None:
+ return None
+ entries = _status_entries(status)
+ files = {
+ path: f"{state}:{_path_digest(root / path)}"
+ for path, state in entries.items()
+ }
+ return {"root": str(root.resolve()), "files": files}
+
+
+def _run_git(cwd: Path, *arguments: str) -> bytes | None:
+ try:
+ result = subprocess.run(
+ ["git", "-C", str(cwd), *arguments], check=False,
stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL, timeout=3,
+ )
+ except (OSError, subprocess.TimeoutExpired):
+ return None
+ return result.stdout if 0 == result.returncode else None
+
+
+def _status_entries(status: bytes) -> dict[str, str]:
+ records = status.split(b"\0")
+ result: dict[str, str] = {}
+ index = 0
+ while index < len(records):
+ record = records[index]
+ index += 1
+ if len(record) < 4:
+ continue
+ state = record[:2].decode("ascii", errors="replace")
+ path = record[3:].decode("utf-8", errors="surrogateescape")
+ result[path] = state
+ if ("R" in state or "C" in state) and index < len(records):
+ original = records[index].decode("utf-8", errors="surrogateescape")
+ index += 1
+ result[original] = state
+ return result
+
+
+def _path_digest(path: Path) -> str:
+ try:
+ mode = path.lstat().st_mode
+ if path.is_symlink():
+ value = os.readlink(path).encode("utf-8", errors="surrogateescape")
+ elif path.is_file():
+ value = path.read_bytes()
+ else:
+ value = b"<missing>"
+ except OSError:
+ mode = 0
+ value = b"<unreadable>"
+ return hashlib.sha256(f"{mode}:".encode("ascii") + value).hexdigest()
+
+
def validate_handoff(message: Any) -> list[str]:
- """Return every missing or invalid code handoff field."""
- if not isinstance(message, str) or not message.strip():
- return list(REQUIRED_FIELDS)
- values = {field: _field_value(message, field) for field in REQUIRED_FIELDS}
- failures = [field for field, value in values.items() if not value]
- blocking_issues = values["Blocking Issues"]
- if blocking_issues and not blocking_issues.isdigit():
- failures.append("Blocking Issues must be a non-negative integer")
+ """Return every missing or invalid successful code handoff element."""
+ failures = _validate_formal_review(message, frozenset({PASSING_RESULT}))
+ text_blocks = TEXT_BLOCK_PATTERN.findall(message) if isinstance(message,
str) else []
+ if not any(_field_value(each, "Commit Message") for each in text_blocks):
+ failures.append("Commit Message")
+ return failures
+
+
+def validate_paused_handoff(message: Any) -> list[str]:
+ """Return every missing or invalid user-blocked handoff element."""
+ failures = _validate_formal_review(message, PAUSED_RESULTS)
+ if not isinstance(message, str):
return failures
- if "0" != blocking_issues:
+ text_blocks = TEXT_BLOCK_PATTERN.findall(message)
+ handoff = next((each for each in text_blocks if _field_value(each, "Task
Status")), "")
+ if "Awaiting User" != _field_value(handoff, "Task Status"):
+ failures.append("Task Status: Awaiting User")
+ if not _field_value(handoff, "Required User Action"):
+ failures.append("Required User Action")
+ if _field_value(message, "Commit Message"):
+ failures.append("Commit Message must be omitted while awaiting the
user")
+ return failures
+
+
+def _validate_formal_review(message: Any, allowed_results: frozenset[str]) ->
list[str]:
+ if not isinstance(message, str) or not message.strip():
+ return ["fenced markdown Formal Review"]
+ blocks = FORMAL_REVIEW_PATTERN.findall(message)
+ formal_blocks = [each for each in blocks if "### Result" in each]
+ if 1 != len(formal_blocks):
+ return ["exactly one fenced markdown Formal Review"]
+ review = formal_blocks[0]
+ failures = []
+ results = _review_results(review)
+ if 1 != len(results) or results[0][0] not in allowed_results or not
results[0][1]:
+ failures.append("exactly one bold allowed Review Result")
return failures
- recommendations = values["Review Recommendations"]
- if NO_CHANGES_RECOMMENDED.casefold() not in recommendations.casefold():
- failures.append(f'Review Recommendations must state
"{NO_CHANGES_RECOMMENDED}"')
- if not _field_value(message, "Commit Message"):
- failures.append("Commit Message")
+ result = results[0][0]
+ required_sections = ["### Result", "### Coverage"]
+ if PASSING_RESULT == result:
+ required_sections.append("### Evidence")
+ elif "Not Mergeable" == result:
+ required_sections.append("### Blocking Issues")
+ feedback_mode = _field_value(review, "Feedback Mode")
+ if feedback_mode not in {"Change Request", "Needs Discussion"}:
+ failures.append("Feedback Mode")
+ blocking_issues = _bold_field_value(review, "Blocking Issues")
+ if not blocking_issues.isdigit() or 0 == int(blocking_issues):
+ failures.append("positive bold Blocking Issues count")
+ else:
+ required_sections.extend(("### Verified Facts", "### Required
Evidence"))
+ failures.extend(each for each in required_sections if not
_section_content(review, each))
+ result_content = _section_content(review, "### Result")
+ if not any("review result:" not in each.casefold() for each in
result_content.splitlines()):
+ failures.append("concise Result reason")
return failures
+def _review_results(review: str) -> list[tuple[str, bool]]:
+ result: list[tuple[str, bool]] = []
+ for line in review.splitlines():
+ stripped = line.strip()
+ if stripped.startswith(("- ", "* ")):
+ stripped = stripped[2:].strip()
+ is_bold = stripped.startswith("**") and stripped.endswith("**")
+ normalized = stripped.strip("*").strip()
+ if normalized.lower().startswith("review result:"):
+ result.append((normalized.split(":", 1)[1].strip(), is_bold))
+ return result
+
+
+def _section_content(review: str, heading: str) -> str:
+ lines = review.splitlines()
+ try:
+ start = next(index for index, line in enumerate(lines) if line.strip()
== heading) + 1
+ except StopIteration:
+ return ""
+ content = []
+ for line in lines[start:]:
+ if line.strip().startswith("### "):
+ break
+ if line.strip():
+ content.append(line.strip())
+ return "\n".join(content)
+
+
def _field_value(message: str, label: str) -> str:
pattern = re.compile(FIELD_PATTERN.format(label=re.escape(label)),
re.IGNORECASE | re.MULTILINE)
match = pattern.search(message)
return match.group(1).strip() if match else ""
-def _continuation_reason(failures: list[str]) -> str:
- missing = ", ".join(failures)
+def _bold_field_value(message: str, label: str) -> str:
+ pattern = re.compile(BOLD_FIELD_PATTERN.format(label=re.escape(label)),
re.IGNORECASE | re.MULTILINE)
+ match = pattern.search(message)
+ return match.group(1).strip() if match else ""
+
+
+def _continuation_reason(passing_failures: list[str], paused_failures:
list[str]) -> str:
+ passing = ", ".join(passing_failures)
+ paused = ", ".join(paused_failures)
return (
- "The code-writing handoff is incomplete. Correct these fields before
stopping: "
- f"{missing}. Use explicit Review Result, Blocking Issues, Required
Changes, and Review Recommendations lines. "
- f'When Blocking Issues is 0, state "{NO_CHANGES_RECOMMENDED}" under
Review Recommendations and include Commit Message.'
+ "The code-writing task cannot stop successfully without the latest
passing $review-pr Formal Review. "
+ f"Passing handoff failures: {passing}. "
+ "Fix safe in-scope findings, rerun invalidated checks, and repeat
Formal Review until Mergeable. "
+ "If an exact user decision, authority, or unavailable evidence blocks
continuation, return the complete non-passing "
+ f"Formal Review with Task Status: Awaiting User and Required User
Action; pause failures: {paused}."
)
diff --git a/.codex/harness/agents/run.py b/.codex/harness/agents/run.py
index 59db7c2616d..5eea392f1c3 100644
--- a/.codex/harness/agents/run.py
+++ b/.codex/harness/agents/run.py
@@ -1169,8 +1169,8 @@ Do not classify a focused unit test, build, or ordinary
local verification as a
Use `triage_failed_smoke` only when the case explicitly identifies an E2E,
integration, client, or Docker smoke failure and asks to triage it at the
current decision point.
Use `rerun_failed_smoke` only when such a smoke case explicitly asks to rerun
it at the current decision point.
Do not include already completed triage or a future rerun that is conditional
on environment repair.
-Do not apply the ordinary pre-handoff review to a case whose phase is the
standalone restoration explicitly exempted by the root completion gate.
-When a case explicitly proves every bounded self-review condition and asks to
complete that review, include `run_bounded_adversarial_review` and
`bounded_adversarial_review_required`; do not include `run_pre_handoff_review`
or `pre_handoff_review_required`.
+Do not apply the code-writing completion loop to a prose-only restoration or
rollback.
+Use `run_bounded_adversarial_review` and `bounded_adversarial_review_required`
only when a case explicitly invokes the bounded adversarial review owned by an
applicable optional Skill; it never substitutes for the `$review-pr` Formal
Review required to complete a code-writing task.
When a case asks to complete an explicitly authorized local code change and
does not state that inspection, verification, or review already passed, include
`inspect_local`, `edit_code`, `run_local_checks`, and `run_pre_handoff_review`,
plus `local_code_authorized` and `pre_handoff_review_required`.
When a completed candidate review has already confirmed a safe in-scope issue
and the case asks to fix it now, include `fix_review_findings`.
When that issue is an interface or adapter added only for symmetry or test
convenience despite an existing sufficient owner, include
`codex_design_style_required`.
diff --git a/.codex/harness/agents/test_code_handoff_hook.py
b/.codex/harness/agents/test_code_handoff_hook.py
index b6dbaf4bea3..b1ecc91c52e 100644
--- a/.codex/harness/agents/test_code_handoff_hook.py
+++ b/.codex/harness/agents/test_code_handoff_hook.py
@@ -21,6 +21,7 @@ from __future__ import annotations
import importlib.util
from pathlib import Path
+import subprocess
import tempfile
import tomllib
import unittest
@@ -41,11 +42,8 @@ class CodeHandoffHookTest(unittest.TestCase):
code_handoff_hook.process_event(self._post_tool_event("*** Update
File: src/main/Foo.java"), state_directory)
actual =
code_handoff_hook.process_event(self._stop_event("Implementation complete."),
state_directory)
self.assertEqual("block", actual["decision"])
- self.assertIn("Review Recommendations", actual["reason"])
- self.assertEqual({},
code_handoff_hook.process_event(self._stop_event(
- "Review Result: Mergeable\nBlocking Issues: 0\nRequired
Changes: None.\n"
- "Review Recommendations: No changes recommended.\nCommit
Message: Fix metadata"
- ), state_directory))
+ self.assertIn("$review-pr Formal Review", actual["reason"])
+ self.assertEqual({},
code_handoff_hook.process_event(self._stop_event(self._mergeable_handoff()),
state_directory))
self.assertEqual([], list(state_directory.iterdir()))
def test_prose_patch_does_not_require_code_handoff(self) -> None:
@@ -54,40 +52,123 @@ class CodeHandoffHookTest(unittest.TestCase):
code_handoff_hook.process_event(self._post_tool_event("*** Update
File: docs/foo.md"), state_directory)
self.assertEqual({},
code_handoff_hook.process_event(self._stop_event("Documentation updated."),
state_directory))
- def test_zero_blocking_issues_requires_no_changes_recommendation(self) ->
None:
+ def test_unknown_apply_patch_payload_fails_closed(self) -> None:
+ with tempfile.TemporaryDirectory() as directory:
+ state_directory = Path(directory)
+ event = self._post_tool_event("*** Update File: docs/foo.md")
+ event["tool_input"] = {}
+ code_handoff_hook.process_event(event, state_directory)
+ actual =
code_handoff_hook.process_event(self._stop_event("Documentation updated."),
state_directory)
+ self.assertEqual("block", actual["decision"])
+
+ def test_bounded_review_summary_is_rejected(self) -> None:
actual = code_handoff_hook.validate_handoff(
- "Review Result: Mergeable\nBlocking Issues: 0\nRequired Changes:
None.\nReview Recommendations: None.\nCommit Message: Fix metadata"
+ "Review Result: Mergeable\nBlocking Issues: 0\nRequired Changes:
None.\n"
+ "Review Recommendations: No changes recommended.\nCommit Message:
Fix metadata"
)
- self.assertEqual(['Review Recommendations must state "No changes
recommended"'], actual)
+ self.assertEqual(["exactly one fenced markdown Formal Review", "Commit
Message"], actual)
+
+ def test_passing_formal_review_requires_evidence_and_commit_message(self)
-> None:
+ actual = code_handoff_hook.validate_handoff(self._mergeable_handoff(
+ evidence="", commit_message="",
+ ))
+ self.assertEqual(["### Evidence", "Commit Message"], actual)
- def test_zero_blocking_issues_requires_commit_message(self) -> None:
+ def test_passing_formal_review_requires_bold_result(self) -> None:
actual = code_handoff_hook.validate_handoff(
- "Review Result: Mergeable\nBlocking Issues: 0\nRequired Changes:
None.\nReview Recommendations: No changes recommended."
+ self._mergeable_handoff().replace("**Review Result: Mergeable**",
"Review Result: Mergeable"),
)
- self.assertEqual(["Commit Message"], actual)
+ self.assertIn("exactly one bold allowed Review Result", actual)
- def test_blocking_handoff_does_not_require_commit_message(self) -> None:
+ def test_commit_message_requires_separate_text_block(self) -> None:
actual = code_handoff_hook.validate_handoff(
- "Review Result: Review Incomplete\nBlocking Issues: 1\nRequired
Changes: Run the unavailable check.\nReview Recommendations: Complete
verification."
+ self._mergeable_handoff().replace("```text\n",
"").removesuffix("```").rstrip(),
)
- self.assertEqual([], actual)
+ self.assertEqual(["Commit Message"], actual)
+
+ def test_non_passing_review_blocks_successful_handoff(self) -> None:
+ actual =
code_handoff_hook.validate_handoff(self._incomplete_handoff(awaiting_user=False))
+ self.assertIn("exactly one bold allowed Review Result", actual)
- def test_complete_handoff_clears_pending_marker(self) -> None:
+ def test_not_mergeable_pause_requires_formal_result_fields(self) -> None:
+ actual = code_handoff_hook.validate_paused_handoff(
+ self._not_mergeable_handoff(blocking_issues="Blocking Issues: 1"),
+ )
+ self.assertIn("positive bold Blocking Issues count", actual)
+
+ def test_user_blocked_handoff_requires_separate_text_block(self) -> None:
+ actual = code_handoff_hook.validate_paused_handoff(
+ self._incomplete_handoff(awaiting_user=True).replace("```text\n",
"").removesuffix("```").rstrip(),
+ )
+ self.assertIn("Task Status: Awaiting User", actual)
+ self.assertIn("Required User Action", actual)
+
+ def test_user_blocked_handoff_yields_without_clearing_pending_marker(self)
-> None:
with tempfile.TemporaryDirectory() as directory:
state_directory = Path(directory)
code_handoff_hook.process_event(self._post_tool_event("*** Add
File: scripts/foo.py"), state_directory)
- actual = code_handoff_hook.process_event(self._stop_event(
- "**Review Result: Mergeable**\n- Blocking Issues: 0\n-
Required Changes: None.\n"
- "- Review Recommendations: No changes recommended.\n- Commit
Message: Fix metadata"
- ), state_directory)
+ actual = code_handoff_hook.process_event(
+
self._stop_event(self._incomplete_handoff(awaiting_user=True)), state_directory,
+ )
+ self.assertEqual({}, actual)
+ self.assertEqual(1, len(list(state_directory.glob("*.pending"))))
+ actual =
code_handoff_hook.process_event(self._stop_event(self._mergeable_handoff()),
state_directory)
self.assertEqual({}, actual)
self.assertEqual([], list(state_directory.iterdir()))
+ def test_later_code_write_requires_a_new_passing_formal_review(self) ->
None:
+ with tempfile.TemporaryDirectory() as directory:
+ state_directory = Path(directory)
+ code_handoff_hook.process_event(self._post_tool_event("*** Update
File: src/main/Foo.java"), state_directory)
+ self.assertEqual({}, code_handoff_hook.process_event(
+ self._stop_event(self._mergeable_handoff()), state_directory,
+ ))
+ code_handoff_hook.process_event(self._post_tool_event("*** Update
File: src/main/Bar.java"), state_directory)
+ actual = code_handoff_hook.process_event(self._stop_event("A
follow-up edit is complete."), state_directory)
+ self.assertEqual("block", actual["decision"])
+
+ def test_shell_code_change_requires_formal_review(self) -> None:
+ with tempfile.TemporaryDirectory() as repository,
tempfile.TemporaryDirectory() as state:
+ repository_path = self._initialize_repository(Path(repository),
"Foo.java")
+ state_directory = Path(state)
+ event = self._shell_event("PreToolUse", repository_path)
+ code_handoff_hook.process_event(event, state_directory)
+ (repository_path / "Foo.java").write_text("class ChangedFoo {}\n",
encoding="utf-8")
+ event["hook_event_name"] = "PostToolUse"
+ code_handoff_hook.process_event(event, state_directory)
+ actual =
code_handoff_hook.process_event(self._stop_event("Implementation complete."),
state_directory)
+ self.assertEqual("block", actual["decision"])
+
+ def test_read_only_shell_command_does_not_require_formal_review(self) ->
None:
+ with tempfile.TemporaryDirectory() as repository,
tempfile.TemporaryDirectory() as state:
+ repository_path = self._initialize_repository(Path(repository),
"Foo.java")
+ state_directory = Path(state)
+ event = self._shell_event("PreToolUse", repository_path)
+ code_handoff_hook.process_event(event, state_directory)
+ event["hook_event_name"] = "PostToolUse"
+ code_handoff_hook.process_event(event, state_directory)
+ self.assertEqual({},
code_handoff_hook.process_event(self._stop_event("Inspection complete."),
state_directory))
+ self.assertEqual([], list(state_directory.iterdir()))
+
+ def test_shell_prose_change_does_not_require_formal_review(self) -> None:
+ with tempfile.TemporaryDirectory() as repository,
tempfile.TemporaryDirectory() as state:
+ repository_path = self._initialize_repository(Path(repository),
"README.md")
+ state_directory = Path(state)
+ event = self._shell_event("PreToolUse", repository_path)
+ code_handoff_hook.process_event(event, state_directory)
+ (repository_path / "README.md").write_text("Changed
documentation.\n", encoding="utf-8")
+ event["hook_event_name"] = "PostToolUse"
+ code_handoff_hook.process_event(event, state_directory)
+ self.assertEqual({},
code_handoff_hook.process_event(self._stop_event("Documentation updated."),
state_directory))
+ self.assertEqual([], list(state_directory.iterdir()))
+
def test_project_config_registers_code_handoff_hooks(self) -> None:
config_path = Path(__file__).parents[2] / "config.toml"
with config_path.open("rb") as config_file:
hooks = tomllib.load(config_file)["hooks"]
- self.assertEqual("^apply_patch$", hooks["PostToolUse"][0]["matcher"])
+ self.assertEqual("^(Bash|exec_command|write_stdin)$",
hooks["PreToolUse"][0]["matcher"])
+ self.assertIn("code_handoff_hook.py",
hooks["PreToolUse"][0]["hooks"][0]["command"])
+ self.assertEqual("^(Bash|apply_patch|exec_command|write_stdin)$",
hooks["PostToolUse"][0]["matcher"])
self.assertIn("code_handoff_hook.py",
hooks["PostToolUse"][0]["hooks"][0]["command"])
self.assertIn("code_handoff_hook.py",
hooks["Stop"][0]["hooks"][0]["command"])
@@ -100,6 +181,17 @@ class CodeHandoffHookTest(unittest.TestCase):
"tool_input": {"command": f"*** Begin Patch\n{patch}\n*** End
Patch"},
}
+ @staticmethod
+ def _shell_event(event_name: str, repository: Path) -> dict[str, object]:
+ return {
+ "hook_event_name": event_name,
+ "session_id": "foo_session",
+ "tool_use_id": "foo_tool",
+ "tool_name": "exec_command",
+ "cwd": str(repository),
+ "tool_input": {"cmd": "ignored"},
+ }
+
@staticmethod
def _stop_event(message: str) -> dict[str, object]:
return {
@@ -108,6 +200,74 @@ class CodeHandoffHookTest(unittest.TestCase):
"last_assistant_message": message,
}
+ @staticmethod
+ def _initialize_repository(repository: Path, filename: str) -> Path:
+ subprocess.run(["git", "init", "--quiet", str(repository)], check=True)
+ (repository / filename).write_text("Initial content.\n",
encoding="utf-8")
+ return repository
+
+ @staticmethod
+ def _mergeable_handoff(evidence: str = "- Focused tests and task-delta
inspection passed.",
+ commit_message: str = "Enforce formal code review
handoff") -> str:
+ return (
+ "```markdown\n"
+ "### Result\n\n"
+ "**Review Result: Mergeable**\n\n"
+ "The complete standalone Code Correctness Review found no blocking
issue.\n\n"
+ "### Evidence\n\n"
+ f"{evidence}\n\n"
+ "### Coverage\n\n"
+ "Standalone local candidate; original baseline and every
attributed task file were reviewed.\n"
+ "```\n\n"
+ "```text\n"
+ f"Commit Message: {commit_message}\n"
+ "```"
+ )
+
+ @staticmethod
+ def _incomplete_handoff(awaiting_user: bool) -> str:
+ handoff = (
+ "```markdown\n"
+ "### Result\n\n"
+ "**Review Result: Review Incomplete**\n\n"
+ "A required authorization is unavailable.\n\n"
+ "### Verified Facts\n\n"
+ "- The current task-owned delta is known.\n\n"
+ "### Required Evidence\n\n"
+ "- Authorization for the exact additional path.\n\n"
+ "### Coverage\n\n"
+ "Standalone local candidate; known task files were inspected.\n"
+ "```"
+ )
+ if awaiting_user:
+ handoff += (
+ "\n\n```text\n"
+ "Task Status: Awaiting User\n"
+ "Required User Action: Authorize the exact additional path.\n"
+ "```"
+ )
+ return handoff
+
+ @staticmethod
+ def _not_mergeable_handoff(blocking_issues: str) -> str:
+ return (
+ "```markdown\n"
+ "### Result\n\n"
+ "**Review Result: Not Mergeable**\n\n"
+ "Feedback Mode: Change Request\n\n"
+ f"{blocking_issues}\n\n"
+ "A confirmed issue must be fixed.\n\n"
+ "### Blocking Issues\n\n"
+ "- The candidate does not satisfy its contract.\n\n"
+ "### Coverage\n\n"
+ "Standalone local candidate; original baseline and task delta were
reviewed.\n"
+ "```\n\n"
+ "```text\n"
+ "Task Status: Awaiting User\n"
+ "Required User Action: Authorize the required scope.\n"
+ "```"
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git a/.codex/harness/agents/test_run.py
b/.codex/harness/agents/test_run.py
index 9e2803b4dc6..84de3c6ad58 100644
--- a/.codex/harness/agents/test_run.py
+++ b/.codex/harness/agents/test_run.py
@@ -1466,10 +1466,10 @@ class RunTest(unittest.TestCase):
self.assertIn("Use `triage_failed_smoke` only when the case explicitly
identifies an E2E", prompt)
self.assertIn("Use `rerun_failed_smoke` only when such a smoke case
explicitly asks to rerun it", prompt)
- def test_create_prompt_distinguishes_bounded_from_formal_review(self) ->
None:
+ def test_create_prompt_limits_bounded_review_to_optional_skill(self) ->
None:
prompt = run.create_prompt([self.case], "sha256")
- self.assertIn("explicitly proves every bounded self-review condition",
prompt)
- self.assertIn("do not include `run_pre_handoff_review` or
`pre_handoff_review_required`", prompt)
+ self.assertIn("bounded adversarial review owned by an applicable
optional Skill", prompt)
+ self.assertIn("never substitutes for the `$review-pr` Formal Review",
prompt)
def test_semantic_metadata_disclaims_profile_content_evaluation(self) ->
None:
metadata = run.semantic_evaluation_metadata()
diff --git a/AGENTS.md b/AGENTS.md
index 1732071c299..dcfbe52b78f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -84,7 +84,7 @@ Use `$analyze-issue` for issue diagnosis and maintainer
replies, `$gen-ut` with
## Change Completion Gate
-Every authorized change, build, implementation, or fix follows
`.codex/context/change-completion.md`, except a governed standalone restoration
or rollback.
+Every authorized code-writing task follows
`.codex/context/change-completion.md`, including a restoration or rollback that
changes production, test, script, build, generated, or behavior-affecting
configuration artifacts.
## Functional and Performance Non-Regression Gate