Skip to content

Commit 12429e2

Browse files
committed
Limit Codex feedback retry rounds
1 parent 23d73aa commit 12429e2

5 files changed

Lines changed: 93 additions & 4 deletions

File tree

.github/workflows/codex_pr_feedback.yml

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
BRANCH_NAME: ${{ github.event.workflow_run.head_branch }}
2323
RUN_URL: ${{ github.event.workflow_run.html_url }}
2424
RUN_NAME: ${{ github.event.workflow_run.name }}
25+
MAX_CODEX_FEEDBACK_ROUNDS: "3"
2526
run: |
2627
mkdir -p data/output/codex_feedback
2728
gh pr list --state open --head "${BRANCH_NAME}" --json number,title,url,body > data/output/codex_feedback/pr.json
@@ -64,7 +65,48 @@ jobs:
6465
Path("data/output/codex_feedback/comment.md").write_text(comment.strip() + "\n", encoding="utf-8")
6566
PY
6667
if [ -f data/output/codex_feedback/issue_number.txt ]; then
67-
gh issue comment "$(cat data/output/codex_feedback/issue_number.txt)" --body-file data/output/codex_feedback/comment.md
68+
issue_number="$(cat data/output/codex_feedback/issue_number.txt)"
69+
gh issue view "${issue_number}" --comments --json comments > data/output/codex_feedback/issue.json
70+
python3 - <<'PY'
71+
import json
72+
import os
73+
import textwrap
74+
from pathlib import Path
75+
76+
output_dir = Path("data/output/codex_feedback")
77+
issue = json.loads((output_dir / "issue.json").read_text(encoding="utf-8"))
78+
comments = [comment.get("body") or "" for comment in issue.get("comments", [])]
79+
previous_rounds = sum(body.startswith("<!-- codex-pr-feedback:") for body in comments)
80+
max_rounds = int(os.environ.get("MAX_CODEX_FEEDBACK_ROUNDS", "3"))
81+
comment_path = output_dir / "comment.md"
82+
if previous_rounds >= max_rounds:
83+
comment = textwrap.dedent(
84+
f"""\
85+
<!-- codex-pr-feedback:limit -->
86+
## Codex PR Retry Limit Reached
87+
88+
Automatic Codex feedback reached the retry limit.
89+
90+
- Previous feedback rounds: `{previous_rounds}`
91+
- Maximum automatic rounds: `{max_rounds}`
92+
93+
The workflow removed `codex-bridge` from this issue. Please inspect the PR and re-apply the label only if another automated Codex pass is still appropriate.
94+
"""
95+
)
96+
comment_path.write_text(comment.strip() + "\n", encoding="utf-8")
97+
(output_dir / "limit_reached").write_text("true\n", encoding="utf-8")
98+
else:
99+
attempt = previous_rounds + 1
100+
comment = comment_path.read_text(encoding="utf-8").rstrip()
101+
comment_path.write_text(
102+
f"{comment}\n\n- Feedback round: `{attempt}` of `{max_rounds}`\n",
103+
encoding="utf-8",
104+
)
105+
PY
106+
if [ -f data/output/codex_feedback/limit_reached ]; then
107+
gh issue edit "${issue_number}" --remove-label codex-bridge || true
108+
fi
109+
gh issue comment "${issue_number}" --body-file data/output/codex_feedback/comment.md
68110
else
69111
cat data/output/codex_feedback/skip.txt >> "$GITHUB_STEP_SUMMARY"
70112
fi
@@ -85,6 +127,7 @@ jobs:
85127
REVIEW_URL: ${{ github.event.review.html_url }}
86128
REVIEW_AUTHOR: ${{ github.event.review.user.login }}
87129
REVIEW_BODY: ${{ github.event.review.body }}
130+
MAX_CODEX_FEEDBACK_ROUNDS: "3"
88131
run: |
89132
mkdir -p data/output/codex_feedback
90133
python3 - <<'PY'
@@ -122,7 +165,48 @@ jobs:
122165
Path("data/output/codex_feedback/comment.md").write_text(comment.strip() + "\n", encoding="utf-8")
123166
PY
124167
if [ -f data/output/codex_feedback/issue_number.txt ]; then
125-
gh issue comment "$(cat data/output/codex_feedback/issue_number.txt)" --body-file data/output/codex_feedback/comment.md
168+
issue_number="$(cat data/output/codex_feedback/issue_number.txt)"
169+
gh issue view "${issue_number}" --comments --json comments > data/output/codex_feedback/issue.json
170+
python3 - <<'PY'
171+
import json
172+
import os
173+
import textwrap
174+
from pathlib import Path
175+
176+
output_dir = Path("data/output/codex_feedback")
177+
issue = json.loads((output_dir / "issue.json").read_text(encoding="utf-8"))
178+
comments = [comment.get("body") or "" for comment in issue.get("comments", [])]
179+
previous_rounds = sum(body.startswith("<!-- codex-pr-feedback:") for body in comments)
180+
max_rounds = int(os.environ.get("MAX_CODEX_FEEDBACK_ROUNDS", "3"))
181+
comment_path = output_dir / "comment.md"
182+
if previous_rounds >= max_rounds:
183+
comment = textwrap.dedent(
184+
f"""\
185+
<!-- codex-pr-feedback:limit -->
186+
## Codex PR Retry Limit Reached
187+
188+
Automatic Codex feedback reached the retry limit.
189+
190+
- Previous feedback rounds: `{previous_rounds}`
191+
- Maximum automatic rounds: `{max_rounds}`
192+
193+
The workflow removed `codex-bridge` from this issue. Please inspect the PR and re-apply the label only if another automated Codex pass is still appropriate.
194+
"""
195+
)
196+
comment_path.write_text(comment.strip() + "\n", encoding="utf-8")
197+
(output_dir / "limit_reached").write_text("true\n", encoding="utf-8")
198+
else:
199+
attempt = previous_rounds + 1
200+
comment = comment_path.read_text(encoding="utf-8").rstrip()
201+
comment_path.write_text(
202+
f"{comment}\n\n- Feedback round: `{attempt}` of `{max_rounds}`\n",
203+
encoding="utf-8",
204+
)
205+
PY
206+
if [ -f data/output/codex_feedback/limit_reached ]; then
207+
gh issue edit "${issue_number}" --remove-label codex-bridge || true
208+
fi
209+
gh issue comment "${issue_number}" --body-file data/output/codex_feedback/comment.md
126210
else
127211
cat data/output/codex_feedback/skip.txt >> "$GITHUB_STEP_SUMMARY"
128212
fi

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ The monthly optimization planner creates repo-scoped issues for follow-up tasks.
569569

570570
The `codex-bridge` label is consumed by the self-hosted VPS ccbot/Codex runner. Codex should open a draft PR from `codex/monthly-optimization-issue-<issue-number>`, include `<!-- auto-optimization-pr:issue-<issue-number> -->` in the PR body, and mark the PR ready only after targeted tests pass. The post-CI `auto_merge_optimization_pr.yml` workflow can merge Codex PRs only when the PR is non-draft, carries `auto-merge-ok`, has the expected marker, reports task-level auto-merge eligibility, and touches no guarded selector/config paths.
571571

572-
If a Codex remediation PR fails CI or receives a changes-requested review, `codex_pr_feedback.yml` comments the failure or review summary back to the source `codex-bridge` issue. Because the VPS bridge re-dispatches updated issues, Codex can fix the same PR branch without manual handoff.
572+
If a Codex remediation PR fails CI or receives a changes-requested review, `codex_pr_feedback.yml` comments the failure or review summary back to the source `codex-bridge` issue. Because the VPS bridge re-dispatches updated issues, Codex can fix the same PR branch without manual handoff. The workflow allows up to three automatic feedback rounds; after that it removes `codex-bridge` so the issue waits for human review.
573573

574574
## Dynamic Universe Logic
575575

docs/operator_runbook.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ The monthly optimization planner may create repo-scoped follow-up issues after A
8080

8181
Codex remediation PRs must use branch `codex/monthly-optimization-issue-<issue-number>`, include `<!-- auto-optimization-pr:issue-<issue-number> -->` in the PR body, and start as draft. The auto-merge workflow only merges after CI passes, the PR is ready for review, `auto-merge-ok` is present, task-level auto-merge eligibility is recorded, and changed files stay outside guarded selector/config paths.
8282

83-
If CI fails on a Codex remediation PR, or a reviewer requests changes, `Codex PR Feedback` comments the failure or review summary back to the source `codex-bridge` issue. The issue update lets the VPS bridge dispatch Codex again to fix the same PR branch.
83+
If CI fails on a Codex remediation PR, or a reviewer requests changes, `Codex PR Feedback` comments the failure or review summary back to the source `codex-bridge` issue. The issue update lets the VPS bridge dispatch Codex again to fix the same PR branch. The workflow permits up to three automatic feedback rounds, then removes `codex-bridge` and leaves the issue for human review.
8484

8585
## Standard Monthly Flow
8686

scripts/prepare_auto_optimization_pr.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
REPO_NAME_ALIASES = {
110110
"CryptoLeaderRotation": "CryptoSnapshotPipelines",
111111
"crypto-codex-bridge": "CryptoSnapshotPipelines",
112+
"CryptoSnapshotPipelinesCodexBridge": "CryptoSnapshotPipelines",
112113
}
113114

114115

tests/test_auto_optimization_pr_workflow_config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ def test_codex_feedback_workflow_requeues_failed_ci_and_review_feedback(self) ->
6969
self.assertIn("codex/monthly-optimization-issue-", workflow)
7070
self.assertIn("auto-optimization-pr:issue-", workflow)
7171
self.assertIn("gh issue comment", workflow)
72+
self.assertIn('MAX_CODEX_FEEDBACK_ROUNDS: "3"', workflow)
73+
self.assertIn("gh issue edit", workflow)
74+
self.assertIn("--remove-label codex-bridge", workflow)
75+
self.assertIn("Codex PR Retry Limit Reached", workflow)
7276
self.assertIn("Codex PR CI Feedback", workflow)
7377
self.assertIn("Codex PR Review Feedback", workflow)
7478

0 commit comments

Comments
 (0)