Repository navigation
feat: automate codex feedback loop and localize eligibility #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| --- | ||
| description: Review a PR by number - checkout, compare against main, run security checks, and return merge guidance | ||
| args: | ||
| - name: pr | ||
| description: PR number (e.g. 42) | ||
| required: true | ||
| --- | ||
|
|
||
| Review PR #{{pr}} with this workflow: | ||
|
|
||
| ## 1. Gather context | ||
|
|
||
| Run in parallel: | ||
| - `gh pr view {{pr}} --json title,body,headRefName,baseRefName,files,additions,deletions,author` | ||
| - Read relevant baseline files in current `main` (affected frontend components, tauri commands, workflows, tests) | ||
| - Read translation/i18n and release policy docs if touched (`CONTRIBUTING.md`, `docs/choices.md`, `docs/breadcrumbs.md`) | ||
|
|
||
| ## 2. Checkout and read complete diff | ||
|
|
||
| - `gh pr checkout {{pr}}` | ||
| - Read all changed files in the PR, not only highlighted hunks | ||
| - Validate tests and workflows impacted by the change | ||
|
|
||
| ## 3. Review checklist | ||
|
|
||
| Check: | ||
| - Correctness and regression risk (frontend + tauri + swift bridge where applicable) | ||
| - Security and privacy impact (permissions, commands, external calls, secrets) | ||
| - i18n consistency (no mixed-language output for selected app language) | ||
| - CI compatibility (coverage thresholds, clippy, build) | ||
| - Contributor ergonomics (docs/scripts updated when contributor workflow changes) | ||
| - Test coverage for changed behavior (new branches and failure paths) | ||
|
|
||
| ## 4. Classify findings | ||
|
|
||
| Group by severity: | ||
| - Blocker: security/data loss/broken release behavior | ||
| - High: likely user-visible bug or broken contributor flow | ||
| - Medium: convention mismatch, missing test, maintainability risk | ||
| - Low: minor cleanup/nits | ||
|
|
||
| ## 5. Present result and action options | ||
|
|
||
| Return: | ||
| - Findings first, sorted by severity, with file references | ||
| - Explicit recommendation: | ||
| 1. Request changes | ||
| 2. Comment-only follow-up | ||
| 3. Safe to merge | ||
|
|
||
| If user chooses review posting: | ||
| - Use `gh pr review {{pr}} --comment` (or `--request-changes` if needed) | ||
| - Keep comment concise and actionable | ||
|
|
||
| After review actions: | ||
| - `git checkout main` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| name: Codex Feedback Loop | ||
|
|
||
| on: | ||
| pull_request_review: | ||
| types: [submitted] | ||
| issue_comment: | ||
| types: [created] | ||
| workflow_dispatch: | ||
| inputs: | ||
| pr_number: | ||
| description: "PR number to process (required for manual runs)" | ||
| required: true | ||
| type: string | ||
| review_id: | ||
| description: "Optional review id (limits findings to one review)" | ||
| required: false | ||
| type: string | ||
|
|
||
| permissions: | ||
| contents: read | ||
| issues: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| request-codex-fix: | ||
| if: >- | ||
| github.event_name == 'workflow_dispatch' || | ||
| (github.event_name == 'pull_request_review' && | ||
| github.event.review.user.login == 'chatgpt-codex-connector[bot]' && | ||
| github.event.review.state == 'commented') || | ||
| (github.event_name == 'issue_comment' && | ||
| github.event.issue.pull_request && | ||
| startsWith(github.event.comment.body, '/codex-fix')) | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Resolve PR and review context | ||
| id: ctx | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | ||
| PR="${{ inputs.pr_number }}" | ||
| REVIEW_ID="${{ inputs.review_id }}" | ||
| elif [ "${{ github.event_name }}" = "pull_request_review" ]; then | ||
| PR="${{ github.event.pull_request.number }}" | ||
| REVIEW_ID="${{ github.event.review.id }}" | ||
| else | ||
| PR="${{ github.event.issue.number }}" | ||
| REVIEW_ID="" | ||
| fi | ||
|
|
||
| if [ -z "$PR" ]; then | ||
| echo "Missing PR number." | ||
| exit 1 | ||
| fi | ||
|
|
||
| STATE=$(gh pr view "$PR" --repo "$GITHUB_REPOSITORY" --json state --jq .state) | ||
| echo "pr_number=$PR" >> "$GITHUB_OUTPUT" | ||
| echo "review_id=$REVIEW_ID" >> "$GITHUB_OUTPUT" | ||
| echo "pr_state=$STATE" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Stop if PR is not open | ||
| if: steps.ctx.outputs.pr_state != 'OPEN' | ||
| run: echo "PR #${{ steps.ctx.outputs.pr_number }} is not open; skipping." | ||
|
|
||
| - name: Collect codex findings | ||
| if: steps.ctx.outputs.pr_state == 'OPEN' | ||
| id: findings | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| PR_NUMBER: ${{ steps.ctx.outputs.pr_number }} | ||
| REVIEW_ID: ${{ steps.ctx.outputs.review_id }} | ||
| run: | | ||
| if [ -n "$REVIEW_ID" ]; then | ||
| RAW=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments" --paginate) | ||
| FINDINGS=$(echo "$RAW" | jq '[.[] | select(.user.login=="chatgpt-codex-connector[bot]")]') | ||
| else | ||
| RAW=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/comments" --paginate) | ||
| FINDINGS=$(echo "$RAW" | jq '[.[] | select(.user.login=="chatgpt-codex-connector[bot]")]') | ||
| fi | ||
|
|
||
| COUNT=$(echo "$FINDINGS" | jq 'length') | ||
| echo "count=$COUNT" >> "$GITHUB_OUTPUT" | ||
|
|
||
| if [ "$COUNT" -eq 0 ]; then | ||
| echo "No codex review findings." | ||
| exit 0 | ||
| fi | ||
|
|
||
| SUMMARY=$(echo "$FINDINGS" | jq -r ' | ||
| .[:5] | ||
| | map("- `" + (.path // "unknown") + ":" + ((.line // 0) | tostring) + "` " + (.body | gsub("\\n"; " ") | .[0:180])) | ||
| | join("\n") | ||
| ') | ||
|
|
||
| { | ||
| echo "summary<<EOF" | ||
| echo "$SUMMARY" | ||
| echo "EOF" | ||
| } >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Prevent duplicate autofix request | ||
| if: steps.ctx.outputs.pr_state == 'OPEN' && steps.findings.outputs.count != '0' | ||
| id: dedupe | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| PR_NUMBER: ${{ steps.ctx.outputs.pr_number }} | ||
| REVIEW_ID: ${{ steps.ctx.outputs.review_id }} | ||
| run: | | ||
| MARKER="<!-- codex-autofix:pr-${PR_NUMBER}:review-${REVIEW_ID:-latest} -->" | ||
| FOUND=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" --paginate --jq ".[] | select(.body | contains(\"$MARKER\")) | .id" | head -n 1 || true) | ||
| echo "marker=$MARKER" >> "$GITHUB_OUTPUT" | ||
| if [ -n "$FOUND" ]; then | ||
| echo "already=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "already=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Ask codex to apply feedback | ||
| if: steps.ctx.outputs.pr_state == 'OPEN' && steps.findings.outputs.count != '0' && steps.dedupe.outputs.already != 'true' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| PR_NUMBER: ${{ steps.ctx.outputs.pr_number }} | ||
| MARKER: ${{ steps.dedupe.outputs.marker }} | ||
| SUMMARY: ${{ steps.findings.outputs.summary }} | ||
| COUNT: ${{ steps.findings.outputs.count }} | ||
| run: | | ||
| gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body "$(cat <<EOF | ||
| $MARKER | ||
| Codex review findings detected ($COUNT item(s)). | ||
|
|
||
| @codex address that feedback | ||
|
|
||
| Top findings: | ||
| $SUMMARY | ||
| EOF | ||
| )" | ||
|
|
||
| - name: No-op summary | ||
| if: steps.ctx.outputs.pr_state == 'OPEN' && (steps.findings.outputs.count == '0' || steps.dedupe.outputs.already == 'true') | ||
| run: | | ||
| echo "No new codex autofix request posted." | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Codex Feedback Loop + Review Playbook | ||
|
|
||
| ## Scope | ||
| - Add a reusable PR review playbook command (`.cursor/commands/pr-review.md`). | ||
| - Add automated codex follow-up workflow for review findings. | ||
| - Fix mixed-language AI eligibility reasons by honoring selected app language. | ||
|
|
||
| ## Design | ||
| - Workflow `.github/workflows/codex-feedback-loop.yml`: | ||
| - Triggers on codex review submission, `/codex-fix` PR comments, and manual dispatch. | ||
| - Collects codex inline findings from PR review comments. | ||
| - Posts a deduplicated follow-up comment: `@codex address that feedback`. | ||
| - Settings frontend passes resolved app language into `get_apple_intelligence_eligibility`. | ||
| - Rust backend resolves that language and localizes eligibility reason strings. | ||
|
|
||
| ## Verification | ||
| - `npm test` | ||
| - `cd src-tauri && cargo test --quiet` | ||
| - Workflow syntax sanity via local YAML inspection |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
/codex-fix(orworkflow_dispatchwithoutreview_id) runs,REVIEW_IDis empty, so this marker falls back toreview-latest; after the first manual autofix comment is posted, every later manual trigger on the same PR is suppressed, even if new Codex findings were added. This breaks the documented manual retry path because dedupe is keyed to a static token instead of the current review context.Useful? React with 👍 / 👎.