Skip to content

feat(cli): add deterministic patch reviews - #655

Closed
mldangelo-oai wants to merge 155 commits into
mainfrom
mdangelo/codex/refresh-deterministic-patch-reviews
Closed

feat(cli): add deterministic patch reviews#655
mldangelo-oai wants to merge 155 commits into
mainfrom
mdangelo/codex/refresh-deterministic-patch-reviews

Conversation

@mldangelo-oai

@mldangelo-oai mldangelo-oai commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add optional independent minimality and style reviews to patch-producing CLI workflows. Merge current main, preserve patch-risk assessment, and bind automatic publication to the reviewed candidate.

Changes

  • Add --review-minimality and --review-style to patch and scan --patch, both off by default. Minimality runs first. Each selected stage allows one revision by default; --max-review-revisions N sets a shared nonnegative revision budget. Later-stage revisions restart earlier reviews.
  • Derive review scope from the pre-author worktree snapshot, preserve pre-existing changes, and check reviewed Git entries before publication, including direct issue patches followed by risk assessment.
  • Preserve normal unreviewed clean filters, disable review-time filters consistently, preserve materialized symlink modes, recheck reviewer context, and stop unverifiable billed turns under an explicit cost limit.
  • Show normalized publication diffs alongside raw worktree diffs when they differ; preserve non-UTF-8 inspection bytes explicitly.
  • Remove duplicate Git wrappers, nested status/diff calls, and rejection handling. Consolidate 57 repeated test Git implementations; this cleanup removes 120 net lines from the merged baseline, including regression coverage.
  • Refresh the bundled plugin to 0.1.81 and use the existing async child-process pattern for the failing Windows JUnit fixture. Retain the inherited patch-risk contract improvements, which overlap feat(plugin): strengthen patch-risk falsifiers #658.

Testing

  • bun test --timeout 30000 --seed 655 over CLI patch/skills/schema, patch-risk contract, runtime, and JUnit-report tests: 489 passed, 14 platform skips, zero failures.

  • Failing-first regressions for filter handling, reviewer context, symlink representation, cost receipts, post-review publication changes, raw inspection bytes, and normalized publication diffs now pass.

  • Real bundled Codex cache upgrades from 0.1.37 and 0.1.60 replace stale validator content and preserve credentials.

  • Types/generated-model freshness, formatting, build, Ruff, Python 3.10 grammar, and git diff --check: passed.

  • Both built Node inspection entrypoints, 286-entry package validation, and full installed-package smoke: passed.

  • Native Windows/Linux, live model quality, and current-head CI were not run locally. CI is intentionally left for the second pass.

  • Final main refresh (fd98a90): package 0.1.21 includes the MCP launcher-permission fix; SDK implementation and bundled payload are unchanged. Types/model generation, formatting, build, 28 focused tests, static artifact verification and full installed-package smoke passed, including MCP initialization. CI was not awaited.

Risk and rollout

Reviews are opt-in and add model calls and latency. Unreviewed workflows retain their existing behavior. Reviewed publication fails when the candidate cannot be separated from pre-existing changes. The inherited filesystem and Git-state machinery remains substantial; this pass does not resolve every open review discussion or establish merge readiness. The Windows fixture change passed locally but still needs native CI verification.

Public disclosure review

  • No customer, partner, prospect, or user identities, data, or identifying details are included.
  • No credentials, personal data, private source, scan findings, or nonpublic links or tickets are included.
  • I reviewed the branch name, title, description, commits, changes, comments, logs, screenshots, attachments, and links for public disclosure.

The second attestation remains unchecked because historical commit contact metadata and automated restricted settings links remain in the existing PR history. New examples and fixtures are synthetic; the new commit uses GitHub noreply metadata.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-27T09:19:49.071208Z af2c4fe New commits
🔒 Security Review Completed 2026-08-26T05:55:09.144885Z d0092a8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0092a8a6a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/cli.ts Outdated
Comment on lines +5169 to +5170
for (const expected of reviewPublicationEntries) {
const actual = parsePatchReviewTreeEntry(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate reviewed entries before creating the patch commit

When a reviewed file changes after the final approval—for example, through a concurrent editor or a post-checkout hook—this comparison runs only after switch, add, and commit, so the unreviewed content is already recorded in a local commit before the error is raised. The command then leaves the user on the new patch branch with a commit that failed review-integrity validation; compare the current entries with the approved entries before creating the branch or commit, while retaining a final post-commit check for races.

AGENTS.md reference: sdk/typescript/AGENTS.md:L23-L23

Useful? React with 👍 / 👎.

Comment thread sdk/typescript/src/cli.ts Outdated
Comment on lines +5391 to +5393
try {
await lstat(join(current, ".git"));
return await realpath(current);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Confine nested Git metadata before inspecting its status

When an untrusted scanned directory contains a nested .git file, merely finding that node treats the directory as a repository and later runs git status there. Git explicitly permits such a file to redirect to an arbitrary Git directory (gitrepository-layout), so gitdir: /outside/target/.git causes the review snapshot to read metadata outside the selected repository; an attacker-controlled nested config can also set core.worktree to make status traverse another worktree. Resolve and confine the nested Git directory/worktree before invoking Git, or reject external redirections.

AGENTS.md reference: sdk/typescript/AGENTS.md:L8-L12

Useful? React with 👍 / 👎.

Comment thread sdk/typescript/src/cli.ts Outdated
Comment on lines +5642 to +5643
const paths = listed.split("\0");
if (paths.at(-1) === "") paths.pop();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve raw bytes in NUL-delimited Git path lists

On POSIX, a valid Git filename may contain bytes that are not valid UTF-8, but runPatchReviewGit decodes this ls-files -z output as UTF-8 before it is split and written back as pathspecs. The invalid bytes become U+FFFD, so baseline capture aborts with pathspec ... did not match any files for such repositories. Git 2.43's git add -h describes --pathspec-from-file as reading pathspecs from a file and --pathspec-file-nul as using NUL-separated elements; keep these -z path lists as Buffers end-to-end rather than round-tripping them through strings.

Useful? React with 👍 / 👎.

Comment thread sdk/typescript/src/patch-review-mcp.ts Outdated
) {
throw new Error("Repository inspection requires a confined relative path.");
}
return normalized.replace(/^\.\//u, "").replace(/\/$/u, "");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize dot to the repository root for inspection

When a reviewer passes the conventional root path "." to list_directory or search, treePath(..., true) leaves it as "." instead of converting it to the empty root path. list_directory consequently reports that the path is not a directory, while search silently uses :(top,literal). and returns no matches even when the repository contains the query. Git 2.43's git ls-tree -h describes the trailing operand as a <path>; normalize . to the same root representation used when the optional path is omitted.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d83261daa1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/cli.ts Outdated
const config = configBytes.toString("utf8");
if (
!Buffer.from(config, "utf8").equals(configBytes) ||
/^\s*\[\s*include(?:if)?(?:\s|\")/imu.test(config)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Remove the invalid Unicode regex escape

In every supported Node runtime, the u flag makes \" an invalid identity escape in a regular-expression literal. Consequently, the compiled CLI fails during module parsing with SyntaxError: Invalid regular expression before any command can run; match the quote directly as " instead.

Useful? React with 👍 / 👎.

Comment thread sdk/typescript/src/cli.ts
await runWithTemporaryIndex(["--literal-pathspecs", "add", "--", ...files]);
const currentEntries = parsePatchReviewIndexEntries(
Buffer.from(
await runWithTemporaryIndex(["ls-files", "--stage", "-z", "--", "."]),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid buffering the entire index with the default cap

When a repository's ls-files --stage -z output exceeds Node's default execFile buffer (about 1 MiB), this new whole-index query rejects with a max-buffer error and --create-pr fails before creating the branch. This also affects unreviewed patch publication because the query runs even when reviewPublicationEntries is empty; either request only the paths that need validation or run this Git command without the default buffer limit.

AGENTS.md reference: sdk/typescript/AGENTS.md:L24-L24

Useful? React with 👍 / 👎.

Comment thread sdk/typescript/src/cli.ts Outdated
const removed: Buffer[] = [];
for (const pathBytes of paths) {
const key = patchReviewGitPathKey(pathBytes);
if (ignoredPathSet.has(key)) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve applicable ignored instructions for style review

When a target uses an ignored, local-only AGENTS.md, this unconditional skip removes that instruction file from the immutable baseline. The reviewer runs from the empty temporary review directory with external tools disabled, so it has no other way to discover those applicable instructions and can approve code that violates the very local standards the style stage is supposed to check; convey resolved instruction files to the reviewer while continuing to exclude unrelated ignored content.

Useful? React with 👍 / 👎.

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 568fd5e3e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/cli.ts
Comment thread sdk/typescript/src/cli.ts
@soyeon-oai
soyeon-oai force-pushed the mdangelo/codex/port-patch-risk-assessment branch from ef05f7d to 711c48c Compare August 27, 2026 02:50
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@soyeon-oai
soyeon-oai force-pushed the mdangelo/codex/port-patch-risk-assessment branch from 8e84947 to 711c48c Compare August 27, 2026 02:56
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 91a5cc8503

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d619dab66b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/cli.ts Outdated
],
{ environment, signal },
);
const normalizedCandidate = await normalizedPublicationTree(paths);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Review the normalized bytes that publication will commit

When a candidate path uses .gitattributes working-tree-encoding, the reviewer diff is produced from baselineTree and candidateTree, whose blobs contain raw worktree bytes, while this call separately runs Git normalization and records different objects for automatic publication. With a UTF-16 file, I confirmed that the review delta becomes an opaque GIT binary patch, while the staged publication blob is decoded UTF-8 source; an approval therefore does not cover the representation that --create-pr validates and commits. Generate the review delta from the normalized baseline and candidate trees, or explicitly expose the normalized publication diff to the reviewer.

AGENTS.md reference: sdk/typescript/AGENTS.md:L22-L23

Useful? React with 👍 / 👎.

@soyeon-oai
soyeon-oai force-pushed the mdangelo/codex/port-patch-risk-assessment branch from 0fbbed0 to 711c48c Compare August 27, 2026 03:10
Base automatically changed from mdangelo/codex/port-patch-risk-assessment to main August 27, 2026 03:20
@github-actions github-actions Bot added the enhancement New feature or request label Aug 27, 2026
Merge main, preserve optional risk assessment, validate reviewed publication and usage receipts, and consolidate duplicate review plumbing and fixtures.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1b0270aa0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +105 to +109
if any(
outcome != "hold_for_evidence" for outcome in item["outcomes"].values()
) and not critical_unknown_ids <= resolved:
errors.append(
"terminal evidence outcomes must resolve every decision-critical unknown"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow evidence actions to resolve separate unknowns

When an assessment has multiple decision-critical unknowns with separate evidence actions, this check rejects every action that has a terminal outcome unless that single action claims to resolve all critical unknowns. For example, two actions that honestly resolve one unknown each are rejected even though their combined resolvesUnknowns covers the complete set; the later aggregate coverage check already models that case. Because the schema permits multiple plan actions and the skill says each action should list the IDs it actually resolves, this makes valid multi-unknown hold_for_evidence assessments impossible to validate without falsifying those relationships.

Useful? React with 👍 / 👎.

Comment on lines +86 to +88
revision_evidence = material_failure or any(
item["status"] == "failed" for item in validation
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude irrelevant check failures from revision evidence

When an exact-head check fails for a reason explicitly classified as relevant: false—for example, an unrelated pre-existing formatting failure—this condition still treats it as affirmative evidence that the patch must be revised. The merge branch likewise rejects every failed validation, so an otherwise supported human-review merge cannot be represented, while changing the recommendation to revise is accepted despite there being no patch-related defect. Filter failed checks by relevant just as the auto-merge validation logic already does.

AGENTS.md reference: sdk/typescript/AGENTS.md:L14-L16

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1b0270aa0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +86 to +88
revision_evidence = material_failure or any(
item["status"] == "failed" for item in validation
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect relevance when interpreting failed validation

When an unrelated check fails and is correctly classified with relevant: false, this expression still treats it as affirmative defect evidence; the merge branch likewise rejects every failed check. This contradicts the risk rubric's gate, which excludes only a “failed relevant check” (risk-rubric.md lines 69-74), and prevents an otherwise supported human_review_required merge—for example, a valid patch accompanied by a failed unrelated formatting job—from producing a valid assessment. Filter failed validation entries by relevant when deriving defect evidence and merge eligibility.

Useful? React with 👍 / 👎.

Comment on lines +105 to +109
if any(
outcome != "hold_for_evidence" for outcome in item["outcomes"].values()
) and not critical_unknown_ids <= resolved:
errors.append(
"terminal evidence outcomes must resolve every decision-critical unknown"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow decisive outcomes to resolve a subset of unknowns

When an assessment has multiple decision-critical unknowns, an evidence action that resolves only one may legitimately have a terminal defect outcome—for example, supported keeps the recommendation at hold_for_evidence, while contradicted establishes a defect and changes it to revise regardless of the remaining unknown. This condition rejects that plan because any terminal outcome forces the action to list every critical unknown, contrary to the skill contract that each action lists the specific unknown IDs it resolves (SKILL.md lines 29 and 61). Validate collective coverage separately, but do not require an independently decisive action to claim it resolves unrelated unknowns.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: af2c4fe776

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/cli.ts
reviewRepository!.gitExecutable,
reviewRepository!.repository,
reviewRepository!.tree,
reviewRepository!.objectDirectory,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Seal loose objects before exposing them to the reviewer

When an author turn leaves a subprocess watching the system temporary directory, it can rewrite a loose object beneath objectDirectory while the independent reviewer is running. This line hands that mutable store to the reviewer MCP, and replacing a loose object's compressed contents causes the MCP's git cat-file reads to return the substituted bytes under the existing object ID; the subprocess can then restore the object before the post-review candidate check. This lets an approval cover a forged baseline, so keep the reviewer object store outside the author's writable boundary or authenticate every referenced object before and after the reviewer invocation.

AGENTS.md reference: sdk/typescript/AGENTS.md:L22-L23

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants