Skip to content

feat: add pure review contract identity helpers#81

Open
Pigbibi wants to merge 3 commits into
mainfrom
codex/pr-review-contract-identity-helpers
Open

feat: add pure review contract identity helpers#81
Pigbibi wants to merge 3 commits into
mainfrom
codex/pr-review-contract-identity-helpers

Conversation

@Pigbibi

@Pigbibi Pigbibi commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add pure contract identity helpers for contract_key, behavior_digest, and fingerprint_v2
  • keep fingerprint_v2 stable across severity-only changes
  • distinguish unrelated same-file contracts and opposite behaviors
  • add sanitized fix: classify adapter dispatch outcomes #75/#125 replay identity fixtures

This slice intentionally has no production call-site integration. History persistence, runtime matching, conflict reduction, and the convergence state machine remain unchanged and will land together in the next complete vertical slice.

Verification

  • targeted unittest: 56 passed
  • full unittest discover: 622 passed, 1 skipped
  • ruff check passed
  • compileall passed
  • actionlint passed
  • fixture JSON validation passed
  • git diff check passed

Co-Authored-By: Codex <noreply@openai.com>
@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown

🤖 Codex PR Review

🚫 Merge blocked: 2 serious issue(s) found in high-risk files

🚫 Blocking Issues

These issues must be fixed before this PR can be merged:

1. 🟠 [HIGH] Logic in scripts/run_codex_pr_review.py

_normalize_identity_text() drops all symbolic operators and punctuation by tokenizing with [a-z0-9_]+(?:\.[a-z0-9_]+)*. That makes materially different contracts normalize to the same text, for example x >= limit and x > limit, or a == b and a != b, so _contract_key(), _behavior_digest(), and fingerprint_v2 can collide for distinct bugs. In a production review pipeline this will incorrectly mark new findings as repeats and suppress real issues. (line 809)

Suggestion: Preserve comparison/negation operators in the normalized form, especially inside code spans and predicate text, so semantically different conditions hash differently.

2. 🟠 [HIGH] Logic in scripts/run_codex_pr_review.py

_contract_finding() computes contract_key and behavior_digest from the raw description/suggestion before applying _sanitize_history_text(). As a result, secrets and long-tail text that are later redacted or truncated still influence the fingerprint, so two findings that persist to the same sanitized history record can get different identities. That will fragment replay history and make repeated findings fail to match whenever only the redacted value or truncated suffix changes. (line 860)

Suggestion: Derive contract_key, behavior_digest, and fingerprint_v2 from the sanitized/truncated text that will actually be stored, or sanitize before normalization so persisted history and computed identity stay reproducible.


Review by Codex PR Review bot • PR

@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: 865e212a53

ℹ️ 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 scripts/run_codex_pr_review.py Outdated
Comment thread scripts/run_codex_pr_review.py Outdated
Comment thread scripts/run_codex_pr_review.py Outdated
Comment thread scripts/run_codex_pr_review.py Outdated
Co-Authored-By: Codex <noreply@openai.com>

@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: b2692847e9

ℹ️ 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 scripts/run_codex_pr_review.py Outdated
Co-Authored-By: Codex <noreply@openai.com>

@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: dd128c2a86

ℹ️ 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".

def _contract_key(finding: dict[str, Any]) -> str:
payload = json.dumps(
{
"file": _normalize_identity_text(finding.get("file")),

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 path separators in contract keys

For repositories that contain paths like pkg/foo-bar.py and pkg/foo/bar.py, this line sends the filename through the prose normalizer, which strips both / and - into spaces. Those different files then get the same file component, so identical findings in the two files produce the same contract_key/fingerprint_v2 and any caller using these helpers for history would treat separate contracts as the same one; keep a canonical path string or path-specific sanitizer instead of the word tokenizer here.

Useful? React with 👍 / 👎.

Comment on lines +832 to +833
anchors = re.findall(r"`([^`]{1,120})`", text)
anchors.extend(re.findall(r"\b[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)+\b", text))

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 anchors independent of Markdown formatting

When the same finding is worded with validate() in backticks versus plain validate(), the context tokens are identical but only the backticked version gets an anchor, so the hashed subject and contract_key change solely because of Markdown formatting. For dotted names like DispatchState.apply(), the second regex also captures the same backticked identifier a second time, causing another formatting-only difference; extract anchors consistently and deduplicate them before hashing.

Useful? React with 👍 / 👎.

def _normalize_identity_text(value: Any) -> str:
text = str(value or "").lower()
stop_words = {
"the", "and", "for", "from", "into", "that", "this", "with",

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 Keep directional prepositions in behavior text

For findings where the contract depends on direction, dropping words such as from and into makes opposite requirements collide even though token order is preserved. For example, Move funds from escrow into account and Move funds into escrow from account both normalize to move funds escrow account, so they get the same contract_key, behavior_digest, and fingerprint_v2; retain these directional terms when hashing behavior.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant