From 0e446ecdf2d53b1eaacdad547492d8d7a4c2db35 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 6 Feb 2026 11:27:55 +0000 Subject: [PATCH 1/3] ci: add Checkpoint AI fix workflow --- .github/workflows/checkpoint-fix.yml | 131 +++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 .github/workflows/checkpoint-fix.yml diff --git a/.github/workflows/checkpoint-fix.yml b/.github/workflows/checkpoint-fix.yml new file mode 100644 index 00000000..624039f7 --- /dev/null +++ b/.github/workflows/checkpoint-fix.yml @@ -0,0 +1,131 @@ +name: Checkpoint AI Fix + +on: + repository_dispatch: + types: [checkpoint-fix] + +permissions: + contents: write + pull-requests: write + +jobs: + fix: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Notify running + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "running" + }' + + - name: Create fix branch + run: | + git checkout -b checkpoint-fix/${{ github.event.client_payload.reportId }} + + - name: Write bug context + run: | + cat > /tmp/checkpoint-context.json << 'CONTEXT_EOF' + ${{ toJSON(github.event.client_payload) }} + CONTEXT_EOF + + - name: Install Amp + run: curl -fsSL https://ampcode.com/install.sh | bash + + - name: Run AI Agent + env: + AMP_API_KEY: ${{ secrets.AMP_API_KEY }} + run: | + amp -x --dangerously-allow-all "You are fixing a bug reported by QA via Checkpoint. Here is the bug report: + + Title: ${{ github.event.client_payload.title }} + Description: ${{ github.event.client_payload.description }} + URL: ${{ github.event.client_payload.url }} + + The full bug context (element selectors, computed styles, console errors, failed requests, DOM snapshots) is in /tmp/checkpoint-context.json. Read that file first. + + Find the relevant source files using the CSS selectors and React component names from the context. Fix the bug. Do not add comments explaining the fix - just fix it." + + - name: Commit and push + run: | + git config user.name "checkpoint-bot" + git config user.email "checkpoint@tempo.xyz" + if git diff --quiet; then + echo "No changes to commit" + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "failed", + "error": "Agent produced no changes" + }' + exit 0 + fi + git add -A + git commit -m "fix: ${{ github.event.client_payload.title }} + + Checkpoint Report: ${{ github.event.client_payload.reportId }} + Linear: ${{ github.event.client_payload.issueId }}" + git push origin checkpoint-fix/${{ github.event.client_payload.reportId }} + + - name: Create PR + id: create_pr + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_URL=$(gh pr create \ + --title "fix: ${{ github.event.client_payload.title }}" \ + --body "## Checkpoint Auto-Fix + + **Linear:** [${{ github.event.client_payload.issueId }}](${{ github.event.client_payload.issueUrl }}) + **Report ID:** \`${{ github.event.client_payload.reportId }}\` + **URL:** ${{ github.event.client_payload.url }} + + --- + + This PR was automatically generated by [Checkpoint](https://tempo-qa.vercel.app) in response to a QA bug report. + + ### Bug Description + ${{ github.event.client_payload.description }} + + ### Screenshots + See the linked Linear issue for screenshots and element context." \ + --head "checkpoint-fix/${{ github.event.client_payload.reportId }}" \ + --base main) + + PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') + echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT + echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT + + - name: Notify PR opened + if: steps.create_pr.outputs.pr_url + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "pr_opened", + "prUrl": "${{ steps.create_pr.outputs.pr_url }}", + "prNumber": ${{ steps.create_pr.outputs.pr_number }} + }' + + - name: Notify failure + if: failure() + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "failed", + "error": "Workflow failed" + }' From 3345945ddb1b1381f35a1156453d001fc655d67a Mon Sep 17 00:00:00 2001 From: checkpoint-bot Date: Sat, 7 Feb 2026 10:17:39 +0000 Subject: [PATCH 2/3] ci: update workflow with screenshot context and session mode Amp-Thread-ID: https://ampcode.com/threads/T-019c3787-403d-71da-8195-769706a31c65 Co-authored-by: Amp --- .github/workflows/checkpoint-fix.yml | 104 ++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/.github/workflows/checkpoint-fix.yml b/.github/workflows/checkpoint-fix.yml index 624039f7..0bd3f647 100644 --- a/.github/workflows/checkpoint-fix.yml +++ b/.github/workflows/checkpoint-fix.yml @@ -26,16 +26,48 @@ jobs: "status": "running" }' - - name: Create fix branch + - name: Setup branch + id: branch run: | - git checkout -b checkpoint-fix/${{ github.event.client_payload.reportId }} + SESSION_BRANCH="${{ github.event.client_payload.sessionBranch }}" + if [ -n "$SESSION_BRANCH" ] && git ls-remote --exit-code --heads origin "$SESSION_BRANCH" >/dev/null 2>&1; then + git fetch origin "$SESSION_BRANCH" + git checkout "$SESSION_BRANCH" + echo "name=$SESSION_BRANCH" >> $GITHUB_OUTPUT + echo "is_new=false" >> $GITHUB_OUTPUT + else + BRANCH="checkpoint/${{ github.event.client_payload.reportId }}" + git checkout -b "$BRANCH" + echo "name=$BRANCH" >> $GITHUB_OUTPUT + echo "is_new=true" >> $GITHUB_OUTPUT + fi - - name: Write bug context + - name: Write context run: | cat > /tmp/checkpoint-context.json << 'CONTEXT_EOF' ${{ toJSON(github.event.client_payload) }} CONTEXT_EOF + - name: Download screenshots + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p /tmp/checkpoint-screenshots + URLS=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[]? | .rawUrl // empty') + NAMES=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[]? | .name // empty') + if [ -n "$URLS" ]; then + i=1 + while IFS= read -r url && IFS= read -r name <&3; do + # Gist raw URLs need auth for secret gists + curl -sL -H "Authorization: token $GH_TOKEN" "$url" | base64 -d > "/tmp/checkpoint-screenshots/$name" 2>/dev/null || true + echo "Downloaded screenshot $i: $name" + i=$((i+1)) + done <<< "$URLS" 3<<< "$NAMES" + ls -la /tmp/checkpoint-screenshots/ + else + echo "No screenshots to download" + fi + - name: Install Amp run: curl -fsSL https://ampcode.com/install.sh | bash @@ -43,17 +75,26 @@ jobs: env: AMP_API_KEY: ${{ secrets.AMP_API_KEY }} run: | - amp -x --dangerously-allow-all "You are fixing a bug reported by QA via Checkpoint. Here is the bug report: + SCREENSHOT_FILES=$(ls /tmp/checkpoint-screenshots/ 2>/dev/null | head -5) + SCREENSHOT_NOTE="" + if [ -n "$SCREENSHOT_FILES" ]; then + SCREENSHOT_NOTE="Screenshots of the element/area are in /tmp/checkpoint-screenshots/. Look at these images first to understand visually what needs to change." + fi + + amp -x --dangerously-allow-all "You are an AI agent implementing a change requested via Checkpoint (a QA/feedback tool). The request may be a bug fix, a UI change, a feature tweak, content update, or any other code modification. + + Request: ${{ github.event.client_payload.title }} + Details: ${{ github.event.client_payload.description }} + Page URL: ${{ github.event.client_payload.url }} - Title: ${{ github.event.client_payload.title }} - Description: ${{ github.event.client_payload.description }} - URL: ${{ github.event.client_payload.url }} + ${SCREENSHOT_NOTE} - The full bug context (element selectors, computed styles, console errors, failed requests, DOM snapshots) is in /tmp/checkpoint-context.json. Read that file first. + The full context (element selectors, React component names, computed styles, console errors, failed requests, DOM snapshots, screenshot annotations) is in /tmp/checkpoint-context.json. Read that file first. - Find the relevant source files using the CSS selectors and React component names from the context. Fix the bug. Do not add comments explaining the fix - just fix it." + Use the CSS selectors and React component names from the context to locate the relevant source files. Implement exactly what was requested - whether that is fixing a bug, removing an element, changing text, adjusting styles, or any other modification. Do not add comments explaining the change - just make it." - name: Commit and push + id: commit run: | git config user.name "checkpoint-bot" git config user.email "checkpoint@tempo.xyz" @@ -70,20 +111,22 @@ jobs: exit 0 fi git add -A - git commit -m "fix: ${{ github.event.client_payload.title }} + git commit -m "checkpoint: ${{ github.event.client_payload.title }} Checkpoint Report: ${{ github.event.client_payload.reportId }} Linear: ${{ github.event.client_payload.issueId }}" - git push origin checkpoint-fix/${{ github.event.client_payload.reportId }} + git push origin ${{ steps.branch.outputs.name }} + echo "pushed=true" >> $GITHUB_OUTPUT - name: Create PR id: create_pr + if: steps.commit.outputs.pushed == 'true' && steps.branch.outputs.is_new == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | PR_URL=$(gh pr create \ - --title "fix: ${{ github.event.client_payload.title }}" \ - --body "## Checkpoint Auto-Fix + --title "checkpoint: ${{ github.event.client_payload.title }}" \ + --body "## Checkpoint AI Change **Linear:** [${{ github.event.client_payload.issueId }}](${{ github.event.client_payload.issueUrl }}) **Report ID:** \`${{ github.event.client_payload.reportId }}\` @@ -91,14 +134,14 @@ jobs: --- - This PR was automatically generated by [Checkpoint](https://tempo-qa.vercel.app) in response to a QA bug report. + This PR was automatically generated by [Checkpoint](https://tempo-qa.vercel.app) in response to a request. - ### Bug Description + ### Request ${{ github.event.client_payload.description }} - ### Screenshots + ### Context See the linked Linear issue for screenshots and element context." \ - --head "checkpoint-fix/${{ github.event.client_payload.reportId }}" \ + --head "${{ steps.branch.outputs.name }}" \ --base main) PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') @@ -115,9 +158,34 @@ jobs: "reportId": "${{ github.event.client_payload.reportId }}", "status": "pr_opened", "prUrl": "${{ steps.create_pr.outputs.pr_url }}", - "prNumber": ${{ steps.create_pr.outputs.pr_number }} + "prNumber": ${{ steps.create_pr.outputs.pr_number }}, + "branch": "${{ steps.branch.outputs.name }}" + }' + + - name: Notify commit added + if: steps.commit.outputs.pushed == 'true' && steps.branch.outputs.is_new == 'false' + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "committed", + "branch": "${{ steps.branch.outputs.name }}" }' + - name: Cleanup screenshot gist + if: always() + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + GIST_ID=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[0]?.gistId // empty') + if [ -n "$GIST_ID" ]; then + curl -s -X DELETE "https://api.github.com/gists/$GIST_ID" \ + -H "Authorization: token $GH_TOKEN" || true + echo "Deleted gist $GIST_ID" + fi + - name: Notify failure if: failure() run: | From 32a9989d5a83bdd3730aab3a4c08cdf0ad2c035d Mon Sep 17 00:00:00 2001 From: max-digi Date: Sat, 7 Feb 2026 10:38:27 +0000 Subject: [PATCH 3/3] Update Checkpoint AI fix workflow Amp-Thread-ID: https://ampcode.com/threads/T-019c379d-3381-718a-a051-4dcfe238c5a8 Co-authored-by: Amp --- .github/workflows/fix-workflow.yml | 199 +++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 .github/workflows/fix-workflow.yml diff --git a/.github/workflows/fix-workflow.yml b/.github/workflows/fix-workflow.yml new file mode 100644 index 00000000..0bd3f647 --- /dev/null +++ b/.github/workflows/fix-workflow.yml @@ -0,0 +1,199 @@ +name: Checkpoint AI Fix + +on: + repository_dispatch: + types: [checkpoint-fix] + +permissions: + contents: write + pull-requests: write + +jobs: + fix: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Notify running + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "running" + }' + + - name: Setup branch + id: branch + run: | + SESSION_BRANCH="${{ github.event.client_payload.sessionBranch }}" + if [ -n "$SESSION_BRANCH" ] && git ls-remote --exit-code --heads origin "$SESSION_BRANCH" >/dev/null 2>&1; then + git fetch origin "$SESSION_BRANCH" + git checkout "$SESSION_BRANCH" + echo "name=$SESSION_BRANCH" >> $GITHUB_OUTPUT + echo "is_new=false" >> $GITHUB_OUTPUT + else + BRANCH="checkpoint/${{ github.event.client_payload.reportId }}" + git checkout -b "$BRANCH" + echo "name=$BRANCH" >> $GITHUB_OUTPUT + echo "is_new=true" >> $GITHUB_OUTPUT + fi + + - name: Write context + run: | + cat > /tmp/checkpoint-context.json << 'CONTEXT_EOF' + ${{ toJSON(github.event.client_payload) }} + CONTEXT_EOF + + - name: Download screenshots + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p /tmp/checkpoint-screenshots + URLS=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[]? | .rawUrl // empty') + NAMES=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[]? | .name // empty') + if [ -n "$URLS" ]; then + i=1 + while IFS= read -r url && IFS= read -r name <&3; do + # Gist raw URLs need auth for secret gists + curl -sL -H "Authorization: token $GH_TOKEN" "$url" | base64 -d > "/tmp/checkpoint-screenshots/$name" 2>/dev/null || true + echo "Downloaded screenshot $i: $name" + i=$((i+1)) + done <<< "$URLS" 3<<< "$NAMES" + ls -la /tmp/checkpoint-screenshots/ + else + echo "No screenshots to download" + fi + + - name: Install Amp + run: curl -fsSL https://ampcode.com/install.sh | bash + + - name: Run AI Agent + env: + AMP_API_KEY: ${{ secrets.AMP_API_KEY }} + run: | + SCREENSHOT_FILES=$(ls /tmp/checkpoint-screenshots/ 2>/dev/null | head -5) + SCREENSHOT_NOTE="" + if [ -n "$SCREENSHOT_FILES" ]; then + SCREENSHOT_NOTE="Screenshots of the element/area are in /tmp/checkpoint-screenshots/. Look at these images first to understand visually what needs to change." + fi + + amp -x --dangerously-allow-all "You are an AI agent implementing a change requested via Checkpoint (a QA/feedback tool). The request may be a bug fix, a UI change, a feature tweak, content update, or any other code modification. + + Request: ${{ github.event.client_payload.title }} + Details: ${{ github.event.client_payload.description }} + Page URL: ${{ github.event.client_payload.url }} + + ${SCREENSHOT_NOTE} + + The full context (element selectors, React component names, computed styles, console errors, failed requests, DOM snapshots, screenshot annotations) is in /tmp/checkpoint-context.json. Read that file first. + + Use the CSS selectors and React component names from the context to locate the relevant source files. Implement exactly what was requested - whether that is fixing a bug, removing an element, changing text, adjusting styles, or any other modification. Do not add comments explaining the change - just make it." + + - name: Commit and push + id: commit + run: | + git config user.name "checkpoint-bot" + git config user.email "checkpoint@tempo.xyz" + if git diff --quiet; then + echo "No changes to commit" + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "failed", + "error": "Agent produced no changes" + }' + exit 0 + fi + git add -A + git commit -m "checkpoint: ${{ github.event.client_payload.title }} + + Checkpoint Report: ${{ github.event.client_payload.reportId }} + Linear: ${{ github.event.client_payload.issueId }}" + git push origin ${{ steps.branch.outputs.name }} + echo "pushed=true" >> $GITHUB_OUTPUT + + - name: Create PR + id: create_pr + if: steps.commit.outputs.pushed == 'true' && steps.branch.outputs.is_new == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_URL=$(gh pr create \ + --title "checkpoint: ${{ github.event.client_payload.title }}" \ + --body "## Checkpoint AI Change + + **Linear:** [${{ github.event.client_payload.issueId }}](${{ github.event.client_payload.issueUrl }}) + **Report ID:** \`${{ github.event.client_payload.reportId }}\` + **URL:** ${{ github.event.client_payload.url }} + + --- + + This PR was automatically generated by [Checkpoint](https://tempo-qa.vercel.app) in response to a request. + + ### Request + ${{ github.event.client_payload.description }} + + ### Context + See the linked Linear issue for screenshots and element context." \ + --head "${{ steps.branch.outputs.name }}" \ + --base main) + + PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') + echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT + echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT + + - name: Notify PR opened + if: steps.create_pr.outputs.pr_url + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "pr_opened", + "prUrl": "${{ steps.create_pr.outputs.pr_url }}", + "prNumber": ${{ steps.create_pr.outputs.pr_number }}, + "branch": "${{ steps.branch.outputs.name }}" + }' + + - name: Notify commit added + if: steps.commit.outputs.pushed == 'true' && steps.branch.outputs.is_new == 'false' + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "committed", + "branch": "${{ steps.branch.outputs.name }}" + }' + + - name: Cleanup screenshot gist + if: always() + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + GIST_ID=$(echo '${{ toJSON(github.event.client_payload.screenshotUrls) }}' | jq -r '.[0]?.gistId // empty') + if [ -n "$GIST_ID" ]; then + curl -s -X DELETE "https://api.github.com/gists/$GIST_ID" \ + -H "Authorization: token $GH_TOKEN" || true + echo "Deleted gist $GIST_ID" + fi + + - name: Notify failure + if: failure() + run: | + curl -s -X POST "${{ github.event.client_payload.callbackUrl }}" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${{ secrets.CHECKPOINT_SECRET }}" \ + -d '{ + "reportId": "${{ github.event.client_payload.reportId }}", + "status": "failed", + "error": "Workflow failed" + }'