fix: ContentSearch dialog lacks focus trapping despite aria-modal #902
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
| name: Claude Code | |
| on: | |
| # Auto-review new issues (from humans — bot-created issues don't trigger) | |
| issues: | |
| types: [opened, reopened] | |
| # PR review on open/update | |
| pull_request: | |
| types: [opened, synchronize] | |
| # Respond to @claude mentions in issues/PRs | |
| issue_comment: | |
| types: [created] | |
| # Respond to @claude in PR review comments | |
| pull_request_review_comment: | |
| types: [created] | |
| # Trigger audit-fix after the audit workflow creates issues | |
| # (github-actions[bot] events don't trigger 'issues' — this is the workaround) | |
| workflow_run: | |
| workflows: ["Claude Periodic Audit"] | |
| types: [completed] | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| id-token: write | |
| jobs: | |
| # Collect open audit issues into a matrix — one job per issue | |
| audit-collect: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| concurrency: | |
| group: audit-collect | |
| cancel-in-progress: true | |
| if: >- | |
| (github.event_name == 'issues' && contains(github.event.issue.labels.*.name, 'audit')) || | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') | |
| outputs: | |
| matrix: ${{ steps.collect.outputs.matrix }} | |
| has_issues: ${{ steps.collect.outputs.has_issues }} | |
| steps: | |
| - name: Collect audit issues | |
| id: collect | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| run: | | |
| if [ "$EVENT_NAME" = "issues" ]; then | |
| NUMBERS="$ISSUE_NUMBER" | |
| else | |
| NUMBERS=$(gh issue list --repo "$GITHUB_REPOSITORY" --state open --label audit --json number --jq '.[].number' | tr '\n' ' ') | |
| fi | |
| if [ -z "$NUMBERS" ]; then | |
| echo "has_issues=false" >> "$GITHUB_OUTPUT" | |
| echo 'matrix={"issue":[]}' >> "$GITHUB_OUTPUT" | |
| else | |
| # Build JSON array: "123 456" -> [123,456] | |
| JSON=$(echo "$NUMBERS" | xargs -n1 | jq -R 'tonumber' | jq -sc '.') | |
| echo "has_issues=true" >> "$GITHUB_OUTPUT" | |
| echo "matrix={\"issue\":$JSON}" >> "$GITHUB_OUTPUT" | |
| echo "Will fix issues: $NUMBERS" | |
| fi | |
| # Fix one audit issue per matrix job — independent branches, PRs, and Claude sessions | |
| audit-fix: | |
| needs: audit-collect | |
| if: needs.audit-collect.outputs.has_issues == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| concurrency: | |
| group: audit-fix-${{ matrix.issue }} | |
| cancel-in-progress: false | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 3 | |
| matrix: ${{ fromJSON(needs.audit-collect.outputs.matrix) }} | |
| steps: | |
| # Checkout with PAT so git push creates events that trigger CI | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| token: ${{ secrets.PAT_TOKEN }} | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: ./.github/actions/setup-tauri-deps | |
| - name: Install dependencies | |
| run: npm install -g pnpm && pnpm install --frozen-lockfile | |
| - name: Fix issue #${{ matrix.issue }} | |
| id: fix | |
| uses: anthropics/claude-code-action@v1 | |
| env: | |
| # Claude's gh/git commands use PAT so PRs trigger CI | |
| GH_TOKEN: ${{ secrets.PAT_TOKEN }} | |
| with: | |
| allowed_bots: "claude[bot]" | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| github_token: ${{ secrets.PAT_TOKEN }} | |
| claude_args: "--model opus --max-turns 25 --allowedTools Bash Read Write Edit Glob Grep MultiEdit" | |
| show_full_output: true | |
| prompt: | | |
| Fix audit issue #${{ matrix.issue }}. | |
| Steps: | |
| 1. Read the issue: `gh issue view ${{ matrix.issue }}` | |
| 2. Create a fix branch: `git checkout -b fix/audit-${{ matrix.issue }}` | |
| 3. Apply the suggested fix | |
| 4. Run `pnpm check:all` to verify frontend gates pass | |
| 5. If the fix touches Rust code (src-tauri/), also run `cargo check --manifest-path src-tauri/Cargo.toml` | |
| 6. Commit with message: `fix: <issue title> (Closes #${{ matrix.issue }})` | |
| 7. Push and create a PR: `gh pr create --title "fix: <issue title>" --body "Closes #${{ matrix.issue }}" --label audit` | |
| Do NOT enable auto-merge — a verification step runs after this. | |
| If the fix causes test failures, adjust until gates pass. | |
| If the issue is unclear or unfixable, comment on the issue explaining why. | |
| # Find the PR created by the fix step | |
| - name: Find created PR | |
| id: find-pr | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.PAT_TOKEN }} | |
| run: | | |
| PR=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "fix/audit-${{ matrix.issue }}" --json number --jq '.[0].number // empty') | |
| if [ -n "$PR" ]; then | |
| echo "number=$PR" >> "$GITHUB_OUTPUT" | |
| echo "Found PR #$PR" | |
| else | |
| echo "No PR found for fix/audit-${{ matrix.issue }}" | |
| fi | |
| # Verify the fix in a separate read-only Claude session | |
| - name: Verify fix for #${{ matrix.issue }} | |
| if: steps.find-pr.outputs.number | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| github_token: ${{ secrets.PAT_TOKEN }} | |
| claude_args: "--model opus --max-turns 10 --allowedTools Bash Read Glob Grep" | |
| prompt: | | |
| You are an audit-fix VERIFIER — not an open-ended reviewer. | |
| Your ONLY job is to check whether PR #${{ steps.find-pr.outputs.number }} actually resolves audit issue #${{ matrix.issue }}. | |
| Steps: | |
| 1. Read the issue: `gh issue view ${{ matrix.issue }} --repo "$GITHUB_REPOSITORY"` | |
| 2. Read the PR diff: `gh pr diff ${{ steps.find-pr.outputs.number }} --repo "$GITHUB_REPOSITORY"` | |
| 3. Answer THREE questions: | |
| a. Does the diff address the specific finding described in the issue? | |
| b. Does the fix introduce any obvious regressions (wrong logic, removed unrelated code)? | |
| c. Is the fix minimal and focused (no scope creep)? | |
| Output format — use EXACTLY one of: | |
| - ✅ **VERIFIED** — The audit finding is resolved. [1-sentence explanation] | |
| - ❌ **NOT VERIFIED** — The finding is NOT resolved. [specific reason] | |
| - ⚠️ **PARTIAL** — The finding is partially addressed. [what's missing] | |
| Post your verification as a comment on PR #${{ steps.find-pr.outputs.number }}: | |
| `gh pr comment ${{ steps.find-pr.outputs.number }} --repo "$GITHUB_REPOSITORY" --body "<your output>"` | |
| Rules: | |
| - Do NOT do open-ended code review. Only verify the specific finding. | |
| - Do NOT suggest improvements beyond the finding. | |
| - If you cannot determine the finding, say so. | |
| # Auto-merge after verification | |
| - name: Enable auto-merge | |
| if: steps.find-pr.outputs.number | |
| env: | |
| GH_TOKEN: ${{ secrets.PAT_TOKEN }} | |
| PR_NUMBER: ${{ steps.find-pr.outputs.number }} | |
| run: gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --auto --squash 2>&1 || echo "Auto-merge not available" | |
| # Fallback: verify audit PRs created externally (PAT/App token that triggers workflows) | |
| # Primary verification now runs inline in audit-fix above. | |
| audit-verify: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| concurrency: | |
| group: audit-verify-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| contains(github.event.pull_request.labels.*.name, 'audit') && | |
| (github.event.pull_request.user.login == 'claude[bot]' || | |
| github.event.pull_request.user.login == 'github-actions[bot]') | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| - uses: anthropics/claude-code-action@v1 | |
| id: verify | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| github_token: ${{ github.token }} | |
| claude_args: "--model opus --max-turns 10 --allowedTools Bash Read Glob Grep" | |
| use_sticky_comment: true | |
| prompt: | | |
| You are an audit-fix VERIFIER — not an open-ended reviewer. | |
| Your ONLY job is to check whether this PR actually resolves the linked audit issue. | |
| Steps: | |
| 1. Read the PR description to find the linked issue number (look for "Closes #N") | |
| 2. Read that issue: `gh issue view <N>` | |
| 3. Read the PR diff: `gh pr diff ${{ github.event.pull_request.number }}` | |
| 4. Answer THREE questions: | |
| a. Does the diff address the specific finding described in the issue? | |
| b. Does the fix introduce any obvious regressions (wrong logic, removed unrelated code)? | |
| c. Is the fix minimal and focused (no scope creep)? | |
| Output format — use EXACTLY one of: | |
| - ✅ **VERIFIED** — The audit finding is resolved. [1-sentence explanation] | |
| - ❌ **NOT VERIFIED** — The finding is NOT resolved. [specific reason] | |
| - ⚠️ **PARTIAL** — The finding is partially addressed. [what's missing] | |
| Rules: | |
| - Do NOT do open-ended code review. Only verify the specific finding. | |
| - Do NOT suggest improvements beyond the finding. | |
| - Do NOT approve or request changes — just report verification status. | |
| - If you cannot determine the linked issue, say so. | |
| - name: Enable auto-merge on verification pass | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: gh pr merge "$PR_NUMBER" --auto --squash 2>&1 || echo "Auto-merge not available for this PR" | |
| # General Claude Code: review issues, PRs (non-audit), respond to @claude | |
| claude: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| concurrency: | |
| group: claude-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| if: >- | |
| (github.event_name == 'issues' && !contains(github.event.issue.labels.*.name, 'audit') && !contains(github.event.issue.labels.*.name, 'cost-report')) || | |
| (github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'audit')) || | |
| (github.event_name == 'issue_comment' && !github.event.comment.performed_via_github_app && contains(github.event.comment.body, '@claude')) || | |
| (github.event_name == 'pull_request_review_comment' && !github.event.comment.performed_via_github_app && contains(github.event.comment.body, '@claude')) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| - uses: anthropics/claude-code-action@v1 | |
| id: claude | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| github_token: ${{ github.token }} | |
| claude_args: "--model opus --max-turns 15" | |
| # PR review: consolidate into one comment, add "Fix this" links | |
| use_sticky_comment: true | |
| include_fix_links: true | |
| - name: Enable auto-merge for bot PRs | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| !contains(github.event.pull_request.labels.*.name, 'audit') && | |
| (github.event.pull_request.user.login == 'claude[bot]' || | |
| github.event.pull_request.user.login == 'github-actions[bot]') | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: gh pr merge "$PR_NUMBER" --auto --squash 2>&1 || echo "Auto-merge not available for this PR" |