Skip to content

Codex PR Feedback

Codex PR Feedback #563

name: Codex PR Feedback
"on":
workflow_run:
workflows: ["CI"]
types: [completed]
pull_request_review:
types: [submitted]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
CODEX_AUDIT_ENABLED: ${{ vars.CODEX_AUDIT_ENABLED || 'true' }}
CODEX_AUDIT_BRIDGE_REPOSITORY: ${{ vars.CODEX_AUDIT_BRIDGE_REPOSITORY || 'QuantStrategyLab/AIAuditBridge' }}
CODEX_AUDIT_BRIDGE_REF: ${{ vars.CODEX_AUDIT_BRIDGE_REF || 'main' }}
CODEX_AUDIT_MODE: ${{ vars.CODEX_AUDIT_MODE || 'review_and_fix' }}
CODEX_AUDIT_PROVIDER: ${{ vars.CODEX_AUDIT_PROVIDER || 'auto' }}
CODEX_AUDIT_AUTO_MERGE: ${{ vars.CODEX_AUDIT_AUTO_MERGE || 'false' }}
CODEX_AUDIT_REQUIRED_STATUS_CHECKS: ${{ vars.CODEX_AUDIT_REQUIRED_STATUS_CHECKS || 'test' }}
jobs:
ci-feedback:
if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' && startsWith(github.event.workflow_run.head_branch, 'codex/monthly-review-issue-') && github.event.workflow_run.head_repository.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
issues: write
pull-requests: read
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Post CI failure back to Codex issue
id: feedback
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_NAME: ${{ github.event.workflow_run.head_branch }}
RUN_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
RUN_NAME: ${{ github.event.workflow_run.name }}
MAX_CODEX_FEEDBACK_ROUNDS: ${{ vars.CODEX_AUDIT_MAX_FEEDBACK_ROUNDS || '3' }}
run: |
set -euo pipefail
mkdir -p data/output/codex_feedback
gh pr list --repo "${GITHUB_REPOSITORY}" --state open --head "${BRANCH_NAME}" --json number,title,url,body,headRefOid,headRepository,isCrossRepository \
--jq '[.[] | select(.isCrossRepository == false and .headRepository.nameWithOwner == "'"${GITHUB_REPOSITORY}"'")]' > data/output/codex_feedback/pr.json
python3 - <<'PY'
import json
import os
import re
import textwrap
from pathlib import Path
prs = json.loads(Path("data/output/codex_feedback/pr.json").read_text(encoding="utf-8"))
if not prs:
Path("data/output/codex_feedback/skip.txt").write_text("No open Codex PR found.\n", encoding="utf-8")
raise SystemExit(0)
pr = prs[0]
if str(pr.get("headRefOid") or "") != os.environ["RUN_HEAD_SHA"]:
Path("data/output/codex_feedback/skip.txt").write_text(
"Skipping stale CI failure because the workflow_run head SHA no longer matches the current PR head.\n",
encoding="utf-8",
)
raise SystemExit(0)
body = pr.get("body") or ""
match = re.search(r"<!--\s*codex-monthly-remediation:issue-(\d+)\s*-->", body)
if not match:
Path("data/output/codex_feedback/skip.txt").write_text("No source issue marker found.\n", encoding="utf-8")
raise SystemExit(0)
issue_number = match.group(1)
comment = textwrap.dedent(
f"""\
<!-- codex-pr-feedback:ci:{pr['number']} -->
## Codex PR CI Feedback
CI failed for the Codex remediation PR.
- PR: {pr['url']}
- Branch: `{os.environ['BRANCH_NAME']}`
- Workflow: `{os.environ['RUN_NAME']}`
- Run: {os.environ['RUN_URL']}
Codex should inspect the failing GitHub Actions logs, update the same PR branch, run targeted tests, and keep the PR draft until the fix is verified.
"""
)
Path("data/output/codex_feedback/issue_number.txt").write_text(issue_number, encoding="utf-8")
Path("data/output/codex_feedback/pr_number.txt").write_text(str(pr["number"]), encoding="utf-8")
Path("data/output/codex_feedback/comment.md").write_text(comment.strip() + "\n", encoding="utf-8")
PY
if [ -f data/output/codex_feedback/issue_number.txt ]; then
issue_number="$(cat data/output/codex_feedback/issue_number.txt)"
pr_number="$(cat data/output/codex_feedback/pr_number.txt)"
policy_labels="$(python3 - <<'PY'
import sys
from scripts.check_codex_auto_merge_readiness import DEFAULT_POLICY_PATH, ReadinessError, load_policy_labels
try:
labels = load_policy_labels(DEFAULT_POLICY_PATH)
except ReadinessError as exc:
print(
f"::warning::Skipping stale guarded auto-merge label cleanup because auto-merge policy labels are invalid: {exc}",
file=sys.stderr,
)
raise SystemExit(0)
print(labels["auto_merge_label"])
print(labels["human_review_label"])
PY
)"
guard_label="$(printf '%s\n' "${policy_labels}" | sed -n '1p')"
human_review_label="$(printf '%s\n' "${policy_labels}" | sed -n '2p')"
if [ -n "${guard_label}" ]; then
gh issue edit "${pr_number}" --repo "${GITHUB_REPOSITORY}" --remove-label "${guard_label}" || true
echo "Removed stale guarded auto-merge label ${guard_label} from PR #${pr_number} after CI failure if it existed."
else
echo "Skipped stale guarded auto-merge label cleanup after CI failure because policy labels are invalid."
fi
gh api --paginate --slurp \
"/repos/${GITHUB_REPOSITORY}/issues/${issue_number}/comments?per_page=100" \
> data/output/codex_feedback/comment_pages.json
python3 - <<'PY'
import json
import os
import textwrap
from pathlib import Path
output_dir = Path("data/output/codex_feedback")
comment_pages = json.loads((output_dir / "comment_pages.json").read_text(encoding="utf-8"))
comments = []
for page in comment_pages:
if isinstance(page, list):
comments.extend(comment.get("body") or "" for comment in page if isinstance(comment, dict))
previous_rounds = sum(body.startswith("<!-- codex-pr-feedback:") for body in comments)
try:
configured_max_rounds = int(os.environ.get("MAX_CODEX_FEEDBACK_ROUNDS", "3"))
except ValueError:
configured_max_rounds = 3
max_rounds = min(max(configured_max_rounds, 1), 10)
comment_path = output_dir / "comment.md"
if previous_rounds >= max_rounds:
comment = textwrap.dedent(
f"""\
<!-- codex-pr-feedback:limit -->
## Codex PR Retry Limit Reached
Automatic Codex feedback reached the retry limit.
- Previous feedback rounds: `{previous_rounds}`
- Maximum automatic rounds: `{max_rounds}`
The workflow removed `codex-bridge` from this issue and will try to mark the PR with the configured human-review label. Please inspect the PR and re-apply `codex-bridge` only if another automated Codex pass is still appropriate.
"""
)
comment_path.write_text(comment.strip() + "\n", encoding="utf-8")
(output_dir / "limit_reached").write_text("true\n", encoding="utf-8")
else:
attempt = previous_rounds + 1
comment = comment_path.read_text(encoding="utf-8").rstrip()
comment_path.write_text(
f"{comment}\n\n- Feedback round: `{attempt}` of `{max_rounds}`\n",
encoding="utf-8",
)
PY
if [ -f data/output/codex_feedback/limit_reached ]; then
gh issue edit "${issue_number}" --repo "${GITHUB_REPOSITORY}" --remove-label codex-bridge || true
if [ -n "${human_review_label}" ]; then
gh label create "${human_review_label}" --repo "${GITHUB_REPOSITORY}" --color d93f0b --description "Codex remediation PR requires human review before merge." || true
gh issue edit "${pr_number}" --repo "${GITHUB_REPOSITORY}" --add-label "${human_review_label}" || true
echo "Marked PR #${pr_number} with human-review label ${human_review_label} after retry limit was reached."
else
echo "Skipped adding human-review label after retry limit because policy labels are invalid."
fi
echo "dispatch_feedback=false" >> "$GITHUB_OUTPUT"
else
echo "dispatch_feedback=true" >> "$GITHUB_OUTPUT"
fi
echo "issue_number=${issue_number}" >> "$GITHUB_OUTPUT"
gh issue comment "${issue_number}" --repo "${GITHUB_REPOSITORY}" --body-file data/output/codex_feedback/comment.md
else
echo "dispatch_feedback=false" >> "$GITHUB_OUTPUT"
cat data/output/codex_feedback/skip.txt >> "$GITHUB_STEP_SUMMARY"
fi
- name: Detect Codex Audit GitHub App Credentials
id: codex_review_app_credentials
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
env:
APP_ID: ${{ vars.CROSS_REPO_GITHUB_APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.CROSS_REPO_GITHUB_APP_PRIVATE_KEY }}
run: |
set -euo pipefail
if [ -n "${APP_ID:-}" ] && [ -n "${APP_PRIVATE_KEY:-}" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
fi
- name: Create GitHub App Token For Codex Audit
id: codex_review_app_token
if: steps.codex_review_app_credentials.outputs.available == 'true'
continue-on-error: true
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.CROSS_REPO_GITHUB_APP_ID }}
private-key: ${{ secrets.CROSS_REPO_GITHUB_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: |
AIAuditBridge
permission-actions: write
- name: Check guarded auto-merge readiness
id: auto_merge_readiness
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.CODEX_AUDIT_READINESS_TOKEN || secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
python scripts/check_codex_auto_merge_readiness.py \
--repo "${GITHUB_REPOSITORY}" \
--branch "${{ github.event.repository.default_branch || github.ref_name }}" \
--auto-merge "${CODEX_AUDIT_AUTO_MERGE}" \
--required-status-checks "${CODEX_AUDIT_REQUIRED_STATUS_CHECKS}" \
--summary-file data/output/codex_feedback/codex_auto_merge_readiness.md
- name: Dispatch Codex feedback retry
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
env:
GH_TOKEN: ${{ steps.codex_review_app_token.outputs.token || secrets.CODEX_AUDIT_DISPATCH_TOKEN }}
ISSUE_NUMBER: ${{ steps.feedback.outputs.issue_number }}
SOURCE_REF: ${{ github.event.repository.default_branch || github.ref_name }}
TARGET_REPOSITORY: ${{ env.CODEX_AUDIT_BRIDGE_REPOSITORY }}
REVIEW_MODE: ${{ env.CODEX_AUDIT_MODE }}
REVIEW_PROVIDER: ${{ env.CODEX_AUDIT_PROVIDER }}
AUTO_MERGE_REQUESTED: ${{ env.CODEX_AUDIT_AUTO_MERGE }}
AUTO_MERGE_READINESS_OUTCOME: ${{ steps.auto_merge_readiness.outcome || 'skipped' }}
run: |
set -euo pipefail
if [ -z "${GH_TOKEN:-}" ]; then
echo "Codex audit feedback dispatch requires either a GitHub App token or CODEX_AUDIT_DISPATCH_TOKEN" >&2
exit 1
fi
if [[ ! "${TARGET_REPOSITORY}" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
echo "Invalid Codex audit repository: ${TARGET_REPOSITORY}" >&2
exit 1
fi
case "${REVIEW_MODE}" in
review_only|review_and_fix) ;;
*) echo "Unsupported Codex audit mode: ${REVIEW_MODE}" >&2; exit 1 ;;
esac
case "${REVIEW_PROVIDER}" in
auto|api|anthropic|codex|openai) ;;
*) echo "Unsupported Codex audit provider: ${REVIEW_PROVIDER}" >&2; exit 1 ;;
esac
auto_merge_requested="false"
if [ "${AUTO_MERGE_REQUESTED}" = "true" ] || [ "${AUTO_MERGE_REQUESTED}" = "True" ] || [ "${AUTO_MERGE_REQUESTED}" = "TRUE" ]; then
auto_merge_requested="true"
fi
auto_merge="false"
if [ "${auto_merge_requested}" = "true" ] && [ "${AUTO_MERGE_READINESS_OUTCOME}" = "success" ]; then
auto_merge="true"
fi
if [ "${auto_merge_requested}" = "true" ] && [ "${AUTO_MERGE_READINESS_OUTCOME}" != "success" ]; then
echo "Guarded auto-merge was requested, but readiness did not pass; dispatching Codex feedback retry with auto_merge=false."
fi
gh workflow run codex_audit.yml \
--repo "${TARGET_REPOSITORY}" \
--ref "${CODEX_AUDIT_BRIDGE_REF}" \
--field source_repo="${GITHUB_REPOSITORY}" \
--field source_ref="${SOURCE_REF}" \
--field issue_number="${ISSUE_NUMBER}" \
--field mode="${REVIEW_MODE}" \
--field provider="${REVIEW_PROVIDER}" \
--field auto_merge="${auto_merge}" \
--field task="monthly_snapshot_audit"
echo "Dispatched AIAuditBridge feedback retry for issue #${ISSUE_NUMBER} to ${TARGET_REPOSITORY}"
- name: Upload Codex feedback diagnostics
if: always()
uses: actions/upload-artifact@v7
with:
name: codex-pr-feedback-ci-${{ github.run_id }}
path: data/output/codex_feedback/
if-no-files-found: warn
review-feedback:
if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' && startsWith(github.event.pull_request.head.ref, 'codex/monthly-review-issue-') && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
issues: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Post review feedback back to Codex issue
id: feedback
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_BODY: ${{ github.event.pull_request.body }}
REVIEW_URL: ${{ github.event.review.html_url }}
REVIEW_AUTHOR: ${{ github.event.review.user.login }}
REVIEW_BODY: ${{ github.event.review.body }}
MAX_CODEX_FEEDBACK_ROUNDS: ${{ vars.CODEX_AUDIT_MAX_FEEDBACK_ROUNDS || '3' }}
run: |
set -euo pipefail
mkdir -p data/output/codex_feedback
python3 - <<'PY'
import os
import re
import textwrap
from pathlib import Path
body = os.environ.get("PR_BODY") or ""
match = re.search(r"<!--\s*codex-monthly-remediation:issue-(\d+)\s*-->", body)
if not match:
Path("data/output/codex_feedback/skip.txt").write_text("No source issue marker found.\n", encoding="utf-8")
raise SystemExit(0)
review_body = (os.environ.get("REVIEW_BODY") or "_No review body supplied._").strip()
comment = textwrap.dedent(
f"""\
<!-- codex-pr-feedback:review:{os.environ['PR_NUMBER']} -->
## Codex PR Review Feedback
A review requested changes on the Codex remediation PR.
- PR: {os.environ['PR_URL']}
- Reviewer: @{os.environ['REVIEW_AUTHOR']}
- Review: {os.environ['REVIEW_URL']}
### Review Body
{review_body}
Codex should update the same PR branch, address the requested changes, run targeted tests, and leave the PR draft until the fix is verified.
"""
)
Path("data/output/codex_feedback/issue_number.txt").write_text(match.group(1), encoding="utf-8")
Path("data/output/codex_feedback/comment.md").write_text(comment.strip() + "\n", encoding="utf-8")
PY
if [ -f data/output/codex_feedback/issue_number.txt ]; then
issue_number="$(cat data/output/codex_feedback/issue_number.txt)"
policy_labels="$(python3 - <<'PY'
import sys
from scripts.check_codex_auto_merge_readiness import DEFAULT_POLICY_PATH, ReadinessError, load_policy_labels
try:
labels = load_policy_labels(DEFAULT_POLICY_PATH)
except ReadinessError as exc:
print(
f"::warning::Skipping stale guarded auto-merge label cleanup because auto-merge policy labels are invalid: {exc}",
file=sys.stderr,
)
raise SystemExit(0)
print(labels["auto_merge_label"])
print(labels["human_review_label"])
PY
)"
guard_label="$(printf '%s\n' "${policy_labels}" | sed -n '1p')"
human_review_label="$(printf '%s\n' "${policy_labels}" | sed -n '2p')"
if [ -n "${guard_label}" ]; then
gh issue edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --remove-label "${guard_label}" || true
echo "Removed stale guarded auto-merge label ${guard_label} from PR #${PR_NUMBER} after requested changes if it existed."
else
echo "Skipped stale guarded auto-merge label cleanup after requested changes because policy labels are invalid."
fi
gh api --paginate --slurp \
"/repos/${GITHUB_REPOSITORY}/issues/${issue_number}/comments?per_page=100" \
> data/output/codex_feedback/comment_pages.json
python3 - <<'PY'
import json
import os
import textwrap
from pathlib import Path
output_dir = Path("data/output/codex_feedback")
comment_pages = json.loads((output_dir / "comment_pages.json").read_text(encoding="utf-8"))
comments = []
for page in comment_pages:
if isinstance(page, list):
comments.extend(comment.get("body") or "" for comment in page if isinstance(comment, dict))
previous_rounds = sum(body.startswith("<!-- codex-pr-feedback:") for body in comments)
try:
configured_max_rounds = int(os.environ.get("MAX_CODEX_FEEDBACK_ROUNDS", "3"))
except ValueError:
configured_max_rounds = 3
max_rounds = min(max(configured_max_rounds, 1), 10)
comment_path = output_dir / "comment.md"
if previous_rounds >= max_rounds:
comment = textwrap.dedent(
f"""\
<!-- codex-pr-feedback:limit -->
## Codex PR Retry Limit Reached
Automatic Codex feedback reached the retry limit.
- Previous feedback rounds: `{previous_rounds}`
- Maximum automatic rounds: `{max_rounds}`
The workflow removed `codex-bridge` from this issue and will try to mark the PR with the configured human-review label. Please inspect the PR and re-apply `codex-bridge` only if another automated Codex pass is still appropriate.
"""
)
comment_path.write_text(comment.strip() + "\n", encoding="utf-8")
(output_dir / "limit_reached").write_text("true\n", encoding="utf-8")
else:
attempt = previous_rounds + 1
comment = comment_path.read_text(encoding="utf-8").rstrip()
comment_path.write_text(
f"{comment}\n\n- Feedback round: `{attempt}` of `{max_rounds}`\n",
encoding="utf-8",
)
PY
if [ -f data/output/codex_feedback/limit_reached ]; then
gh issue edit "${issue_number}" --repo "${GITHUB_REPOSITORY}" --remove-label codex-bridge || true
if [ -n "${human_review_label}" ]; then
gh label create "${human_review_label}" --repo "${GITHUB_REPOSITORY}" --color d93f0b --description "Codex remediation PR requires human review before merge." || true
gh issue edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "${human_review_label}" || true
echo "Marked PR #${PR_NUMBER} with human-review label ${human_review_label} after retry limit was reached."
else
echo "Skipped adding human-review label after retry limit because policy labels are invalid."
fi
echo "dispatch_feedback=false" >> "$GITHUB_OUTPUT"
else
echo "dispatch_feedback=true" >> "$GITHUB_OUTPUT"
fi
echo "issue_number=${issue_number}" >> "$GITHUB_OUTPUT"
gh issue comment "${issue_number}" --repo "${GITHUB_REPOSITORY}" --body-file data/output/codex_feedback/comment.md
else
echo "dispatch_feedback=false" >> "$GITHUB_OUTPUT"
cat data/output/codex_feedback/skip.txt >> "$GITHUB_STEP_SUMMARY"
fi
- name: Detect Codex Audit GitHub App Credentials
id: codex_review_app_credentials
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
env:
APP_ID: ${{ vars.CROSS_REPO_GITHUB_APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.CROSS_REPO_GITHUB_APP_PRIVATE_KEY }}
run: |
set -euo pipefail
if [ -n "${APP_ID:-}" ] && [ -n "${APP_PRIVATE_KEY:-}" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
fi
- name: Create GitHub App Token For Codex Audit
id: codex_review_app_token
if: steps.codex_review_app_credentials.outputs.available == 'true'
continue-on-error: true
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.CROSS_REPO_GITHUB_APP_ID }}
private-key: ${{ secrets.CROSS_REPO_GITHUB_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: |
AIAuditBridge
permission-actions: write
- name: Check guarded auto-merge readiness
id: auto_merge_readiness
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.CODEX_AUDIT_READINESS_TOKEN || secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
python scripts/check_codex_auto_merge_readiness.py \
--repo "${GITHUB_REPOSITORY}" \
--branch "${{ github.event.repository.default_branch || github.ref_name }}" \
--auto-merge "${CODEX_AUDIT_AUTO_MERGE}" \
--required-status-checks "${CODEX_AUDIT_REQUIRED_STATUS_CHECKS}" \
--summary-file data/output/codex_feedback/codex_auto_merge_readiness.md
- name: Dispatch Codex feedback retry
if: steps.feedback.outputs.dispatch_feedback == 'true' && contains(fromJSON('["true","True","TRUE"]'), env.CODEX_AUDIT_ENABLED)
env:
GH_TOKEN: ${{ steps.codex_review_app_token.outputs.token || secrets.CODEX_AUDIT_DISPATCH_TOKEN }}
ISSUE_NUMBER: ${{ steps.feedback.outputs.issue_number }}
SOURCE_REF: ${{ github.event.repository.default_branch || github.ref_name }}
TARGET_REPOSITORY: ${{ env.CODEX_AUDIT_BRIDGE_REPOSITORY }}
REVIEW_MODE: ${{ env.CODEX_AUDIT_MODE }}
REVIEW_PROVIDER: ${{ env.CODEX_AUDIT_PROVIDER }}
AUTO_MERGE_REQUESTED: ${{ env.CODEX_AUDIT_AUTO_MERGE }}
AUTO_MERGE_READINESS_OUTCOME: ${{ steps.auto_merge_readiness.outcome || 'skipped' }}
run: |
set -euo pipefail
if [ -z "${GH_TOKEN:-}" ]; then
echo "Codex audit feedback dispatch requires either a GitHub App token or CODEX_AUDIT_DISPATCH_TOKEN" >&2
exit 1
fi
if [[ ! "${TARGET_REPOSITORY}" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
echo "Invalid Codex audit repository: ${TARGET_REPOSITORY}" >&2
exit 1
fi
case "${REVIEW_MODE}" in
review_only|review_and_fix) ;;
*) echo "Unsupported Codex audit mode: ${REVIEW_MODE}" >&2; exit 1 ;;
esac
case "${REVIEW_PROVIDER}" in
auto|api|anthropic|codex|openai) ;;
*) echo "Unsupported Codex audit provider: ${REVIEW_PROVIDER}" >&2; exit 1 ;;
esac
auto_merge_requested="false"
if [ "${AUTO_MERGE_REQUESTED}" = "true" ] || [ "${AUTO_MERGE_REQUESTED}" = "True" ] || [ "${AUTO_MERGE_REQUESTED}" = "TRUE" ]; then
auto_merge_requested="true"
fi
auto_merge="false"
if [ "${auto_merge_requested}" = "true" ] && [ "${AUTO_MERGE_READINESS_OUTCOME}" = "success" ]; then
auto_merge="true"
fi
if [ "${auto_merge_requested}" = "true" ] && [ "${AUTO_MERGE_READINESS_OUTCOME}" != "success" ]; then
echo "Guarded auto-merge was requested, but readiness did not pass; dispatching Codex feedback retry with auto_merge=false."
fi
gh workflow run codex_audit.yml \
--repo "${TARGET_REPOSITORY}" \
--ref "${CODEX_AUDIT_BRIDGE_REF}" \
--field source_repo="${GITHUB_REPOSITORY}" \
--field source_ref="${SOURCE_REF}" \
--field issue_number="${ISSUE_NUMBER}" \
--field mode="${REVIEW_MODE}" \
--field provider="${REVIEW_PROVIDER}" \
--field auto_merge="${auto_merge}" \
--field task="monthly_snapshot_audit"
echo "Dispatched AIAuditBridge feedback retry for issue #${ISSUE_NUMBER} to ${TARGET_REPOSITORY}"
- name: Upload Codex feedback diagnostics
if: always()
uses: actions/upload-artifact@v7
with:
name: codex-pr-feedback-review-${{ github.run_id }}
path: data/output/codex_feedback/
if-no-files-found: warn