harden(ai-issues): gate improvements, pin codex-action, report publish failures

- Require repo-owner authorship or the `ai: fix-approved` label before Codex
  runs on existing-add-on improvements, mirroring the bug path. Closes the
  cost/abuse vector where any external user could auto-trigger expensive Codex
  runs and draft PRs.
- Pin openai/codex-action to a commit SHA (was the mutable @v1 tag) since it
  receives OPENAI_API_KEY.
- Add a catch-all failure reporter to publish_fix so apply/push/PR-create
  failures notify the issue and swap labels instead of failing silently.
- Reject creation of new top-level files in the patch validator (previously
  only new directories were blocked).
- Update triage comment wording and README to match the new gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
alexbelgium
2026-07-23 12:51:33 +02:00
parent ee0c1e2b96
commit c7f5a9a292
3 changed files with 50 additions and 19 deletions

View File

@@ -12,10 +12,10 @@ maintainer.
3. Reports missing essential evidence receive focused questions. 3. Reports missing essential evidence receive focused questions.
4. New add-on requests are marked for maintainer review and are never 4. New add-on requests are marked for maintainer review and are never
implemented by this automation. implemented by this automation.
5. High-confidence improvements to existing add-ons proceed automatically to a 5. High-confidence bugs and existing-add-on improvements opened by the
draft fix attempt. repository owner proceed directly to Codex analysis; those opened by anyone
6. Bugs opened by the repository owner proceed directly to Codex analysis; else wait for a maintainer to add `ai: fix-approved`.
other bugs wait for a maintainer to add `ai: fix-approved`. 6. New add-on requests never enter Codex, regardless of who opens them.
7. Codex edits an isolated checkout without repository write permissions. 7. Codex edits an isolated checkout without repository write permissions.
8. A fresh job applies and validates the patch, pushes a branch, opens a draft 8. A fresh job applies and validates the patch, pushes a branch, opens a draft
pull request, and posts the root-cause report and pull-request URL. pull request, and posts the root-cause report and pull-request URL.

View File

@@ -84,6 +84,11 @@ for file in "${changed_files[@]}"; do
echo "Creating a new top-level directory is not permitted: $top" >&2 echo "Creating a new top-level directory is not permitted: $top" >&2
exit 1 exit 1
fi fi
else
if ! git cat-file -e "$base_ref:$file" 2>/dev/null; then
echo "Creating a new top-level file is not permitted: $file" >&2
exit 1
fi
fi fi
if [[ "$request_category" == "improvement" && -n "$expected_addon" && "$file" != "$expected_addon/"* ]]; then if [[ "$request_category" == "improvement" && -n "$expected_addon" && "$file" != "$expected_addon/"* ]]; then

View File

@@ -261,14 +261,22 @@ jobs:
improvement) improvement)
labels+=("enhancement") labels+=("enhancement")
if [[ "$EXISTING_ADDON" == true ]]; then if [[ "$EXISTING_ADDON" == true ]]; then
labels+=("ai: fix-proposed" "ai: fixing") labels+=("ai: fix-proposed")
body="**Assessment:** ${summary} body="**Assessment:** ${summary}
**Estimated risk:** ${risk} **Estimated risk:** ${risk}
${response} ${response}"
if [[ "$ISSUE_AUTHOR" == "$REPOSITORY_OWNER" ]]; then
labels+=("ai: fixing")
body="${body}
This targets an existing add-on, so repository analysis and a validated draft fix attempt will start automatically." This targets an existing add-on, so repository analysis and a validated draft fix attempt will start automatically because the issue was opened by the repository owner."
else
body="${body}
This targets an existing add-on. A maintainer can approve repository analysis and an automated draft fix attempt by adding the \`ai: fix-approved\` label."
fi
else else
labels+=("ai: maintainer-review") labels+=("ai: maintainer-review")
body="${response} body="${response}
@@ -319,18 +327,16 @@ jobs:
needs.triage.outputs.category == 'improvement' && needs.triage.outputs.category == 'improvement' &&
needs.triage.outputs.existing_addon == 'true' needs.triage.outputs.existing_addon == 'true'
) || ) ||
needs.triage.outputs.category == 'bug'
) &&
(
( (
needs.triage.outputs.category == 'bug' && github.event.action == 'labeled' &&
( github.event.label.name == 'ai: fix-approved'
( ) ||
github.event.action == 'labeled' && (
github.event.label.name == 'ai: fix-approved' (github.event.action == 'opened' || github.event.action == 'reopened') &&
) || github.event.issue.user.login == github.repository_owner
(
(github.event.action == 'opened' || github.event.action == 'reopened') &&
github.event.issue.user.login == github.repository_owner
)
)
) )
) )
needs: [detect_submitter, triage] needs: [detect_submitter, triage]
@@ -395,7 +401,7 @@ jobs:
- name: Run Codex - name: Run Codex
id: codex id: codex
if: steps.prepare.outputs.existing_pr == '' if: steps.prepare.outputs.existing_pr == ''
uses: openai/codex-action@v1 uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56 # v1
with: with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }} openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: codex-prompt.md prompt-file: codex-prompt.md
@@ -652,3 +658,23 @@ jobs:
gh issue edit "$ISSUE_NUMBER" --repo "$REPO" \ gh issue edit "$ISSUE_NUMBER" --repo "$REPO" \
--add-label "ai: pr-created" --add-label "ai: pr-created"
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body "$body" gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body "$body"
- name: Report publication failure
if: failure() && steps.validation.outcome != 'failure'
env:
GH_TOKEN: ${{ secrets.AI_PR_TOKEN || secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
for label in "ai: fix-approved" "ai: fix-proposed" "ai: fixing"; do
gh issue edit "$ISSUE_NUMBER" --repo "$REPO" \
--remove-label "$label" || true
done
gh issue edit "$ISSUE_NUMBER" --repo "$REPO" \
--add-label "ai: maintainer-review" || true
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body \
"### Automated publication failed
A patch was generated but could not be published (applying, pushing, or opening the draft pull request failed), so no pull request was created. A maintainer should review the [workflow run](${RUN_URL})."