Skip to content

fix: add Toggle Case and Remove Blank Lines to shortcuts docs #923

fix: add Toggle Case and Remove Blank Lines to shortcuts docs

fix: add Toggle Case and Remove Blank Lines to shortcuts docs #923

Workflow file for this run

name: Claude Code
on:
# Audit-fix pipeline reacts to [audit]-labeled issues; general issues are not auto-processed.
issues:
types: [opened, reopened]
# Review Claude-proposed PRs
pull_request:
types: [opened, synchronize]
# 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]
# Manual trigger to run audit-fix without re-auditing
workflow_dispatch:
inputs:
max_issues:
description: "Max issues to fix (0 = use default cap of 6)"
required: false
default: "0"
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
jobs:
# Collect open audit issues into a matrix — one job per issue
# Skips issues labeled 'fix-attempted' (failed in a previous run).
# Caps at 6 issues per run to control cost (~$5/issue × 6 = ~$30 max).
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') ||
(github.event_name == 'workflow_dispatch')
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 }}
INPUT_MAX: ${{ github.event.inputs.max_issues || '0' }}
run: |
# Default cap: 6 issues per run (override via workflow_dispatch input)
MAX_ISSUES="${INPUT_MAX:-0}"
if [ "$MAX_ISSUES" = "0" ]; then
MAX_ISSUES=6
fi
if [ "$EVENT_NAME" = "issues" ]; then
# Single issue trigger — no cap, no skip check
NUMBERS="$ISSUE_NUMBER"
else
# Batch mode: get open audit issues, EXCLUDE 'fix-attempted' label
# Sort by issue number (oldest first) so we process in order
NUMBERS=$(gh issue list --repo "$GITHUB_REPOSITORY" \
--state open --label audit \
--json number,labels \
--jq '[.[] | select(.labels | map(.name) | index("fix-attempted") | not)] | sort_by(.number) | .[].number' \
| head -n "$MAX_ISSUES" \
| tr '\n' ' ')
fi
if [ -z "$NUMBERS" ]; then
echo "has_issues=false" >> "$GITHUB_OUTPUT"
echo 'matrix={"issue":[]}' >> "$GITHUB_OUTPUT"
echo "No eligible issues found (fix-attempted issues are skipped)"
else
# Build JSON array: "123 456" -> [123,456]
JSON=$(echo "$NUMBERS" | xargs -n1 | jq -R 'tonumber' | jq -sc '.')
COUNT=$(echo "$JSON" | jq 'length')
echo "has_issues=true" >> "$GITHUB_OUTPUT"
echo "matrix={\"issue\":$JSON}" >> "$GITHUB_OUTPUT"
echo "Will fix $COUNT issues (cap=$MAX_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: 45
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: |
You are fixing a single audit finding in the VMark codebase.
VMark is a Tauri v2 + React 19 + Zustand v5 desktop Markdown editor.
## Step 1: Understand the issue
Run: `gh issue view ${{ matrix.issue }}`
Read the ENTIRE issue body carefully. It contains:
- **Problem**: what's wrong
- **Location**: exact file paths and line numbers
- **Suggested Fix**: step-by-step instructions
- **Scope Guard**: what NOT to touch
- **Verification**: how to confirm the fix
Follow the suggested fix closely. Do not deviate unless it's clearly wrong.
## Step 2: Plan before coding
Before writing any code, read the files listed in "Location".
Verify the problem exists at the stated lines (code may have shifted).
If the issue is outdated or already fixed, comment on the issue and stop.
## Step 3: Fix
- Create a branch: `git checkout -b fix/audit-${{ matrix.issue }}`
- Make ONLY the changes described in the issue
- Stay within the files listed in "Location" — do not touch unrelated files
- If the fix requires a new test, write it next to the source file
- If the fix removes code, also remove its tests (don't leave dead test code)
## Step 4: Verify
- Run `pnpm check:all` (lint + test + build)
- If Rust code changed: `cargo check --manifest-path src-tauri/Cargo.toml`
- Run the specific verification from the issue body
- If tests fail, fix them — but only for code you changed
## Step 5: Ship
- Commit: `fix: <concise description> (Closes #${{ matrix.issue }})`
- Push and create PR:
`gh pr create --title "fix: <title>" --body "Closes #${{ matrix.issue }}" --label audit`
## Anti-patterns (DO NOT)
- Do NOT refactor surrounding code
- Do NOT add features beyond the fix
- Do NOT update documentation unless the issue says to
- Do NOT enable auto-merge (verification step handles that)
- Do NOT spend more than 3 turns debugging a single test failure —
if stuck, comment on the issue with what you tried and stop
## If unfixable
Comment on the issue explaining:
1. What you tried
2. What went wrong
3. What a human would need to do differently
# Label issue as fix-attempted on failure so next run skips it
- name: Label fix-attempted on failure
if: failure()
env:
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
run: |
gh issue edit "${{ matrix.issue }}" --repo "$GITHUB_REPOSITORY" --add-label "fix-attempted" 2>&1 || true
echo "Labeled #${{ matrix.issue }} as fix-attempted — will be skipped on next run"
# 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"
# Review and auto-merge Claude-proposed PRs (non-audit)
claude:
runs-on: ubuntu-latest
timeout-minutes: 15
concurrency:
group: claude-${{ github.event.pull_request.number || github.run_id }}
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: claude
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ github.token }}
claude_args: "--model opus --max-turns 15"
use_sticky_comment: true
- name: Enable auto-merge
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"