diff --git a/.github/workflows/agentready-dev-issue-pr.yml b/.github/workflows/agentready-dev-issue-pr.yml deleted file mode 100644 index 48a86f29..00000000 --- a/.github/workflows/agentready-dev-issue-pr.yml +++ /dev/null @@ -1,796 +0,0 @@ -name: AgentReady Dev - Issue to Draft PR - -on: - issues: - types: [opened, labeled] - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - workflow_dispatch: - inputs: - issue_number: - description: 'Issue number to convert to PR' - required: true - type: number - -permissions: - contents: write - pull-requests: write - issues: write - id-token: write - actions: read - -jobs: - issue-to-pr: - # Trigger on issue opened, labeled with 'ready-for-pr', or @agentready-dev mentions - if: | - (github.event_name == 'issues' && github.event.action == 'opened') || - (github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'ready-for-pr') || - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@agentready-dev')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@agentready-dev')) || - github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - name: Get issue context - id: issue-context - uses: actions/github-script@v8 - with: - script: | - let issueNumber; - let isCommentTrigger = false; - let commentBody = ''; - - if (context.eventName === 'workflow_dispatch') { - issueNumber = context.payload.inputs.issue_number; - } else if (context.eventName === 'issue_comment' || context.eventName === 'pull_request_review_comment') { - // Extract issue/PR number from comment event - if (context.payload.issue) { - issueNumber = context.payload.issue.number; - } else if (context.payload.pull_request) { - issueNumber = context.payload.pull_request.number; - } - isCommentTrigger = true; - commentBody = context.payload.comment?.body || ''; - } else { - issueNumber = context.payload.issue.number; - } - - // Fetch issue details - const issue = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - }); - - // Check if this is already a PR - if (issue.data.pull_request) { - core.setOutput('is_pr', 'true'); - core.setOutput('pr_number', issueNumber); - } else { - core.setOutput('is_pr', 'false'); - } - - // Check if PR already exists for this issue - const prs = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'all', - head: `${context.repo.owner}:feat/issue-${issueNumber}`, - }); - - // Also check for any PR mentioning this issue - const allPrs = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'all', - }); - const linkedPr = allPrs.data.find(pr => - pr.body?.includes(`#${issueNumber}`) || - pr.title?.includes(`#${issueNumber}`) - ); - - core.setOutput('issue_number', issueNumber); - core.setOutput('issue_title', issue.data.title); - core.setOutput('issue_body', issue.data.body || ''); - core.setOutput('issue_author', issue.data.user.login); - core.setOutput('is_comment_trigger', isCommentTrigger.toString()); - core.setOutput('comment_body', commentBody); - core.setOutput('existing_pr_number', linkedPr?.number?.toString() || prs.data[0]?.number?.toString() || ''); - core.setOutput('skip_pr_creation', (linkedPr || prs.data[0]) ? 'true' : 'false'); - - return { - issueNumber, - title: issue.data.title, - body: issue.data.body || '', - author: issue.data.user.login, - isCommentTrigger, - commentBody, - }; - - - name: Read ACL configuration - id: read-acl - uses: actions/github-script@v8 - with: - script: | - // Read the ACL file from the repository - // This provides a list of users allowed to trigger the agent - // Users with write permissions are still allowed even if not in this list - try { - const { data } = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: '.github/agentready-acl.yml', - ref: context.payload.repository?.default_branch || 'main' - }); - const content = Buffer.from(data.content, 'base64').toString(); - // Extract usernames from YAML (handles " - username" format) - const users = content.match(/^\s*-\s*([\w-]+)/gm)?.map(u => u.replace(/^\s*-\s*/, '').trim()) || []; - core.setOutput('allowed_users', users.join(',')); - console.log(`Loaded ${users.length} users from ACL: ${users.join(', ')}`); - } catch (error) { - // If ACL file doesn't exist or is unreadable, fall back to empty list - // Users with write permissions will still be allowed by Claude Code Action - console.log('ACL file not found or unreadable, using empty list (write permission users still allowed)'); - core.setOutput('allowed_users', ''); - } - - - name: Checkout repository - if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Initialize activity log - if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' - id: init-log - run: | - mkdir -p .github/agentready-dev-logs - LOG_FILE=".github/agentready-dev-logs/activity-$(date +%Y%m%d-%H%M%S)-${{ github.run_id }}.jsonl" - echo "log_file=$LOG_FILE" >> $GITHUB_OUTPUT - echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"event\":\"workflow_started\",\"run_id\":\"${{ github.run_id }}\",\"event_name\":\"${{ github.event_name }}\"}" >> "$LOG_FILE" - - # Ensure analysis files directory exists and is writable - mkdir -p .github/agentready-dev-logs - touch .github/agentready-dev-logs/.gitkeep - - - name: Log context - if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' - run: | - echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"agent\":\"context_gatherer\",\"action\":\"gathered_issue_context\",\"issue_number\":\"${{ steps.issue-context.outputs.issue_number }}\",\"is_pr\":\"${{ steps.issue-context.outputs.is_pr }}\",\"skip_pr_creation\":\"${{ steps.issue-context.outputs.skip_pr_creation }}\"}" >> "${{ steps.init-log.outputs.log_file }}" - - - name: Configure Git - if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' - run: | - git config user.name "agentready-dev[bot]" - git config user.email "agentready-dev[bot]@users.noreply.github.com" - - - name: Analyze issue and determine action - if: steps.issue-context.outputs.skip_pr_creation != 'true' - id: analyze-issue - uses: anthropics/claude-code-action@v1 - env: - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - You are the @agentready-dev agent. Analyze this issue to determine if it makes sense to create a draft PR. - - Issue #${{ steps.issue-context.outputs.issue_number }}: ${{ steps.issue-context.outputs.issue_title }} - - Issue body: - ${{ steps.issue-context.outputs.issue_body }} - - First, run the /review-agentready command to analyze this issue. Use the review process to evaluate: - 1. Is this issue actionable and well-defined enough for implementation? - 2. Are there security concerns that need addressing first? - 3. Does this align with AgentReady project goals? - 4. What would be the implementation approach? - - Based on your analysis, decide: - - If it makes sense to create a draft PR: Write "create_pr" (without quotes) to .github/agentready-dev-logs/analysis-decision.txt - - If it doesn't make sense: Write "provide_feedback" (without quotes) to .github/agentready-dev-logs/analysis-decision.txt - - IMPORTANT: - - Write ONLY the value (create_pr or provide_feedback), NOT "OUTPUT=value" - - You MUST create these files using bash commands. Example: - echo "create_pr" > .github/agentready-dev-logs/analysis-decision.txt - echo "Your reasoning here" > .github/agentready-dev-logs/analysis-reasoning.txt - echo "branch-name" > .github/agentready-dev-logs/analysis-branch.txt - - Write your reasoning (2-3 lines max) to .github/agentready-dev-logs/analysis-reasoning.txt - Write a short branch name suggestion (e.g., "add-feature-x" or "fix-bug-y") to .github/agentready-dev-logs/analysis-branch.txt - - CRITICAL: You must create all three files (.github/agentready-dev-logs/analysis-decision.txt, analysis-reasoning.txt, and analysis-branch.txt) using bash echo commands. - - Do NOT post any comment yet - you will self-review your analysis first. - - - name: Verify analysis files exist - if: steps.issue-context.outputs.skip_pr_creation != 'true' - id: verify-analysis-files - run: | - if [ ! -f .github/agentready-dev-logs/analysis-decision.txt ]; then - echo "ERROR: analysis-decision.txt not found. The 'Analyze issue and determine action' step failed to create required files." >&2 - echo "This indicates Claude Code Action did not complete successfully." >&2 - exit 1 - fi - - if [ ! -f .github/agentready-dev-logs/analysis-reasoning.txt ]; then - echo "ERROR: analysis-reasoning.txt not found. The 'Analyze issue and determine action' step failed to create required files." >&2 - echo "This indicates Claude Code Action did not complete successfully." >&2 - exit 1 - fi - - echo "āœ… Analysis files verified" - echo "files_exist=true" >> $GITHUB_OUTPUT - - - name: Extract analysis decision - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.verify-analysis-files.outputs.files_exist == 'true' - id: extract-decision - run: | - DECISION=$(cat .github/agentready-dev-logs/analysis-decision.txt | tr -d '\n' | head -c 50) - # Remove "OUTPUT=" prefix if present - DECISION=$(echo "$DECISION" | sed 's/^OUTPUT=//' | sed 's/^output=//') - # Extract just the value (create_pr or provide_feedback) - DECISION=$(echo "$DECISION" | grep -oE "(create_pr|provide_feedback)" | head -1) - if [ -z "$DECISION" ]; then - echo "ERROR: Invalid decision value in analysis-decision.txt. Expected 'create_pr' or 'provide_feedback'." >&2 - exit 1 - fi - echo "decision=$DECISION" >> $GITHUB_OUTPUT - - REASONING=$(cat .github/agentready-dev-logs/analysis-reasoning.txt) - echo "reasoning<> $GITHUB_OUTPUT - echo "$REASONING" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - if [ -f .github/agentready-dev-logs/analysis-branch.txt ]; then - BRANCH_SUGGESTION=$(cat .github/agentready-dev-logs/analysis-branch.txt | tr -d '\n' | head -c 50) - echo "branch_suggestion=$BRANCH_SUGGESTION" >> $GITHUB_OUTPUT - else - echo "branch_suggestion=" >> $GITHUB_OUTPUT - fi - - - name: Self-review issue analysis - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.extract-decision.outputs.decision != '' && steps.verify-analysis-files.outputs.files_exist == 'true' - id: self-review-analysis - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - Self-review the issue analysis using the /review-agentready command. - - Re-read the original issue #${{ steps.issue-context.outputs.issue_number }} and your analysis. - Read the decision file: cat .github/agentready-dev-logs/analysis-decision.txt - Read the reasoning file: cat .github/agentready-dev-logs/analysis-reasoning.txt - - Check the issue itself for: - 1. Did you miss any security concerns in the issue description? - 2. Are there implementation risks you didn't consider? - 3. Is your analysis thorough and accurate? - 4. Does your reasoning help humans make informed decisions? - - Track your self-review findings: - - Write a summary of what you found/changed to .github/agentready-dev-logs/self-review-summary.txt - - If you found issues: Describe what was missing and what you added - - If no issues: State that the analysis was comprehensive - - If you find issues with your analysis that need to be added: - - Update the decision/reasoning files with the improved analysis - - After updating, write REVIEW_PASSED=true to .github/agentready-dev-logs/analysis-review-passed.txt - - If your analysis is comprehensive and accurate (no issues found): - - Write REVIEW_PASSED=true to .github/agentready-dev-logs/analysis-review-passed.txt - - The goal is to ensure the issue is thoroughly analyzed before proceeding. Only write REVIEW_PASSED=true after you've verified the analysis is complete and accurate. - - Do NOT post any comment yet. - - - name: Check review result - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.extract-decision.outputs.decision != '' - id: check-review - run: | - if [ -f .github/agentready-dev-logs/analysis-review-passed.txt ]; then - REVIEW_PASSED=$(cat .github/agentready-dev-logs/analysis-review-passed.txt | tr -d '\n' | grep -i "true" || echo "false") - echo "review_passed=$REVIEW_PASSED" >> $GITHUB_OUTPUT - else - echo "review_passed=true" >> $GITHUB_OUTPUT - fi - - # Re-read decision in case it was updated during review - if [ -f .github/agentready-dev-logs/analysis-decision.txt ]; then - DECISION=$(cat .github/agentready-dev-logs/analysis-decision.txt | tr -d '\n' | head -c 50) - # Remove "OUTPUT=" prefix if present - DECISION=$(echo "$DECISION" | sed 's/^OUTPUT=//' | sed 's/^output=//') - # Extract just the value (create_pr or provide_feedback) - DECISION=$(echo "$DECISION" | grep -oE "(create_pr|provide_feedback)" | head -1) - if [ -z "$DECISION" ]; then - DECISION="${{ steps.extract-decision.outputs.decision }}" - fi - echo "final_decision=$DECISION" >> $GITHUB_OUTPUT - else - echo "final_decision=${{ steps.extract-decision.outputs.decision }}" >> $GITHUB_OUTPUT - fi - - - name: Extract self-review summary - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' - id: extract-self-review - run: | - if [ -f .github/agentready-dev-logs/self-review-summary.txt ]; then - SUMMARY=$(cat .github/agentready-dev-logs/self-review-summary.txt) - echo "self_review_summary<> $GITHUB_OUTPUT - echo "$SUMMARY" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT - fi - - - name: Handle feedback (no PR creation) - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'provide_feedback' - uses: actions/github-script@v8 - env: - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - FEEDBACK: ${{ steps.extract-decision.outputs.reasoning }} - SELF_REVIEW_SUMMARY: ${{ steps.extract-self-review.outputs.self_review_summary }} - with: - script: | - const logEntry = { - timestamp: new Date().toISOString(), - agent: 'feedback_handler', - action: 'provided_feedback', - issue_number: parseInt(process.env.ISSUE_NUMBER), - feedback: process.env.FEEDBACK, - }; - - // Append to log file - const fs = require('fs'); - fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); - - // Build self-review section - const selfReviewSection = process.env.SELF_REVIEW_SUMMARY && process.env.SELF_REVIEW_SUMMARY !== 'Self-review completed - no changes needed' - ? `\n\n---\n
Self-review results\n\n${process.env.SELF_REVIEW_SUMMARY}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
` - : `\n\n---\n
Self-review results\n\nāœ… Analysis verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
`; - - // Post brief, structured comment - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: parseInt(process.env.ISSUE_NUMBER), - body: `šŸ¤– **@agentready-dev Analysis**\n\n${process.env.FEEDBACK}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`, - }); - - - name: Get default branch - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' - id: default-branch - env: - GH_TOKEN: ${{ github.token }} - run: | - DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name') - echo "branch=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT - - - name: Create feature branch - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' - id: create-branch - env: - GH_TOKEN: ${{ github.token }} - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - ISSUE_TITLE: ${{ steps.issue-context.outputs.issue_title }} - BRANCH_SUGGESTION: ${{ steps.extract-decision.outputs.branch_suggestion || 'implementation' }} - DEFAULT_BRANCH: ${{ steps.default-branch.outputs.branch }} - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - run: | - # Generate branch name: feat/issue#-short-description - # Clean and shorten issue title for branch name - CLEAN_TITLE=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g' | cut -c1-50) - BRANCH_NAME="feat/issue${ISSUE_NUMBER}-${CLEAN_TITLE}" - - # Use suggestion if provided and shorter - if [ -n "$BRANCH_SUGGESTION" ] && [ "$BRANCH_SUGGESTION" != "implementation" ] && [ "$BRANCH_SUGGESTION" != "" ]; then - CLEAN_SUGGESTION=$(echo "$BRANCH_SUGGESTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g') - BRANCH_NAME="feat/issue${ISSUE_NUMBER}-${CLEAN_SUGGESTION}" - fi - - # Checkout default branch and ensure it's up to date - git checkout "${DEFAULT_BRANCH}" - git pull origin "${DEFAULT_BRANCH}" - - # Create and checkout new branch - git checkout -b "${BRANCH_NAME}" - - # Create initial commit with issue reference - mkdir -p .github/pr-placeholders - echo "# Issue #${ISSUE_NUMBER}" > ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - echo "" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - echo "This draft PR was automatically created from issue #${ISSUE_NUMBER}." >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - echo "" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - echo "**Original Issue:** #${ISSUE_NUMBER}" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - - git add ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" - git commit -m "chore: create draft PR branch for issue #${ISSUE_NUMBER}" - - # Push the branch - git push origin "${BRANCH_NAME}" - - echo "branch_name=${BRANCH_NAME}" >> $GITHUB_OUTPUT - - # Log activity - echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"agent\":\"branch_creator\",\"action\":\"created_branch\",\"issue_number\":\"${ISSUE_NUMBER}\",\"branch_name\":\"${BRANCH_NAME}\"}" >> "$LOG_FILE" - - - name: Create draft Pull Request - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' - id: create-pr - uses: actions/github-script@v8 - env: - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - ISSUE_TITLE: ${{ steps.issue-context.outputs.issue_title }} - ISSUE_BODY: ${{ steps.issue-context.outputs.issue_body }} - BRANCH_NAME: ${{ steps.create-branch.outputs.branch_name }} - DEFAULT_BRANCH: ${{ steps.default-branch.outputs.branch }} - ANALYSIS_SUMMARY: ${{ steps.extract-decision.outputs.reasoning }} - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - with: - script: | - const issueNumber = parseInt(process.env.ISSUE_NUMBER); - const issueTitle = process.env.ISSUE_TITLE; - const issueBody = process.env.ISSUE_BODY || ''; - const branchName = process.env.BRANCH_NAME; - const defaultBranch = process.env.DEFAULT_BRANCH; - const analysisSummary = process.env.ANALYSIS_SUMMARY || ''; - - // Create PR title and body - const prTitle = `[Draft] Issue #${issueNumber}: ${issueTitle}`; - const prBody = `## šŸ¤– Auto-generated Draft PR\n\n` + - `This draft PR was automatically created from issue #${issueNumber}.\n\n` + - `**Original Issue:** #${issueNumber}\n\n` + - `**Analysis Summary:**\n${analysisSummary}\n\n` + - `---\n\n` + - `${issueBody}\n\n` + - `---\n\n` + - `*This PR was automatically created by the [@agentready-dev workflow](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/workflows/agentready-dev-issue-pr.yml).*\n` + - `*[View activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})*`; - - // Create the draft PR - const pr = await github.rest.pulls.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: prTitle, - body: prBody, - head: branchName, - base: defaultBranch, - draft: true, - maintainer_can_modify: true, - }); - - console.log(`Created draft PR #${pr.data.number}: ${pr.data.html_url}`); - - // Log activity - const fs = require('fs'); - const logEntry = { - timestamp: new Date().toISOString(), - agent: 'pr_creator', - action: 'created_draft_pr', - issue_number: issueNumber, - pr_number: pr.data.number, - branch_name: branchName, - }; - fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); - - // Review the PR using review-agentready.md - // This will be done in the next step - - core.setOutput('pr_number', pr.data.number); - core.setOutput('pr_url', pr.data.html_url); - - return { - prNumber: pr.data.number, - prUrl: pr.data.html_url, - }; - - - name: Review draft PR code - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.create-pr.outputs.pr_number != '' - id: review-pr-code - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - Run the /review-agentready command on pull request #${{ steps.create-pr.outputs.pr_number }}. - - Review the actual CODE in the PR, focusing on: - - AgentReady attribute compliance - - Security issues (take special care) - - Code quality and correctness - - Best practices - - Generate a brief, structured review comment (2-3 lines summary, use collapsible sections for details). - Write the review to .github/agentready-dev-logs/pr-review.txt - - Also save a copy of the review to .github/agentready-dev-logs/pr-review-initial.txt before self-review. - Use: cp .github/agentready-dev-logs/pr-review.txt .github/agentready-dev-logs/pr-review-initial.txt - - Do NOT post the comment yet - you will self-review the CODE first. - - - name: Self-review the PR code - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.create-pr.outputs.pr_number != '' - id: self-review-pr-code - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - Self-review the actual CODE in pull request #${{ steps.create-pr.outputs.pr_number }} using the /review-agentready command. - - Check the code itself for: - 1. Security vulnerabilities (path traversal, injection, etc.) - 2. Code quality issues (bugs, logic errors, edge cases) - 3. AgentReady attribute compliance - 4. Best practices violations - - Track your self-review findings: - - Write a summary of what you found/changed to .github/agentready-dev-logs/pr-self-review-summary.txt - - Compare the initial review (.github/agentready-dev-logs/pr-review-initial.txt) with your findings - - If you found additional issues: Describe what was missing and what you added - - If no issues: State that the review was comprehensive - - Compare your findings with the review in .github/agentready-dev-logs/pr-review.txt. - If you find additional issues in the code that weren't in the review, update the review file. - If the code review is comprehensive and accurate, write REVIEW_PASSED=true to .github/agentready-dev-logs/pr-review-passed.txt. - If you found issues that need to be added to the review, update .github/agentready-dev-logs/pr-review.txt and write REVIEW_PASSED=true. - - The goal is to ensure the CODE is thoroughly reviewed before showing it to humans. Only write REVIEW_PASSED=true after you've verified the review is complete and accurate. - - Do NOT post any comment yet. - - - name: Extract PR review - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' - id: extract-pr-review - run: | - if [ -f .github/agentready-dev-logs/pr-review.txt ]; then - REVIEW=$(cat .github/agentready-dev-logs/pr-review.txt) - echo "review<> $GITHUB_OUTPUT - echo "$REVIEW" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "review=Review completed" >> $GITHUB_OUTPUT - fi - - if [ -f .github/agentready-dev-logs/pr-review-passed.txt ]; then - REVIEW_PASSED=$(cat .github/agentready-dev-logs/pr-review-passed.txt | tr -d '\n' | grep -i "true" || echo "false") - echo "review_passed=$REVIEW_PASSED" >> $GITHUB_OUTPUT - else - echo "review_passed=true" >> $GITHUB_OUTPUT - fi - - if [ -f .github/agentready-dev-logs/pr-self-review-summary.txt ]; then - SELF_REVIEW_SUMMARY=$(cat .github/agentready-dev-logs/pr-self-review-summary.txt) - echo "self_review_summary<> $GITHUB_OUTPUT - echo "$SELF_REVIEW_SUMMARY" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT - fi - - - name: Post PR review and link to issue - if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.extract-pr-review.outputs.review_passed == 'true' && steps.self-review-pr-code.outputs.REVIEW_PASSED == 'true' - uses: actions/github-script@v8 - env: - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} - PR_URL: ${{ steps.create-pr.outputs.pr_url }} - REVIEW_OUTPUT: ${{ steps.extract-pr-review.outputs.review }} - SELF_REVIEW_SUMMARY: ${{ steps.extract-pr-review.outputs.self_review_summary }} - with: - script: | - const fs = require('fs'); - const issueNumber = parseInt(process.env.ISSUE_NUMBER); - const prNumber = parseInt(process.env.PR_NUMBER); - const prUrl = process.env.PR_URL; - const reviewOutput = process.env.REVIEW_OUTPUT; - const selfReviewSummary = process.env.SELF_REVIEW_SUMMARY; - - // Build self-review section - const selfReviewSection = selfReviewSummary && selfReviewSummary !== 'Self-review completed - no changes needed' - ? `\n\n---\n
Self-review results\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
` - : `\n\n---\n
Self-review results\n\nāœ… Code review verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
`; - - // Post review on PR - const prComment = `šŸ¤– **@agentready-dev PR Review**\n\n${reviewOutput}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: prComment, - }); - - // Link PR to issue - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `šŸ”€ **Draft PR created:** #${prNumber}\n\n${prUrl}\n\n---\n*Generated by @agentready-dev workflow*`, - }); - - // Log activity - const logEntry = { - timestamp: new Date().toISOString(), - agent: 'comment_poster', - action: 'posted_pr_review_and_linked_issue', - issue_number: issueNumber, - pr_number: prNumber, - }; - fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); - - - name: Handle ad-hoc analysis request - if: steps.issue-context.outputs.is_comment_trigger == 'true' - id: analyze-comment - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - You are the @agentready-dev agent. Someone requested analysis with: "${{ steps.issue-context.outputs.comment_body }}" - - Issue/PR context: - - Issue/PR #${{ steps.issue-context.outputs.issue_number }} - - Title: ${{ steps.issue-context.outputs.issue_title }} - - Body: ${{ steps.issue-context.outputs.issue_body }} - - If this is a PR (is_pr=${{ steps.issue-context.outputs.is_pr }}), run the /review-agentready command on the CODE in the PR. - If this is an issue, analyze the issue description and proposed implementation using the review-agentready.md process. - - Provide a brief, structured analysis (2-3 lines summary, use collapsible sections for details). - Focus on what a reviewer would need to know. - Write analysis to .github/agentready-dev-logs/adhoc-analysis.txt - Do NOT post any comment yet - you will self-review the CODE/issue first. - - - name: Self-review ad-hoc analysis - if: steps.issue-context.outputs.is_comment_trigger == 'true' - id: self-review-comment - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_users: ${{ steps.read-acl.outputs.allowed_users }} - prompt: | - Self-review the actual CODE or issue using the /review-agentready command. - - If this is a PR (is_pr=${{ steps.issue-context.outputs.is_pr }}), review the CODE in PR #${{ steps.issue-context.outputs.issue_number }} again. - If this is an issue, re-read issue #${{ steps.issue-context.outputs.issue_number }}. - - Read your analysis file: cat .github/agentready-dev-logs/adhoc-analysis.txt - - Track your self-review findings: - - Write a summary of what you found/changed to .github/agentready-dev-logs/adhoc-self-review-summary.txt - - If you found issues: Describe what was missing and what you added - - If no issues: State that the analysis was comprehensive - - Check for: - 1. Security issues you might have missed in the code/issue - 2. Code quality problems or bugs you didn't catch - 3. Important details that reviewers need to know - 4. Is your analysis thorough and accurate? - - If you find issues you missed, update .github/agentready-dev-logs/adhoc-analysis.txt and write REVIEW_PASSED=true. - If your analysis is comprehensive, write REVIEW_PASSED=true to .github/agentready-dev-logs/adhoc-analysis-passed.txt. - - The goal is to ensure the CODE/issue is thoroughly reviewed before showing it to humans. Only write REVIEW_PASSED=true after you've verified the analysis is complete and accurate. - - Do NOT post any comment yet. - - - name: Extract ad-hoc analysis - if: steps.issue-context.outputs.is_comment_trigger == 'true' - id: extract-analysis - run: | - if [ -f .github/agentready-dev-logs/adhoc-analysis.txt ]; then - ANALYSIS=$(cat .github/agentready-dev-logs/adhoc-analysis.txt) - echo "analysis<> $GITHUB_OUTPUT - echo "$ANALYSIS" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "analysis=Analysis completed" >> $GITHUB_OUTPUT - fi - - if [ -f .github/agentready-dev-logs/adhoc-analysis-passed.txt ]; then - ANALYSIS_PASSED=$(cat .github/agentready-dev-logs/adhoc-analysis-passed.txt | tr -d '\n' | grep -i "true" || echo "false") - echo "analysis_passed=$ANALYSIS_PASSED" >> $GITHUB_OUTPUT - else - echo "analysis_passed=true" >> $GITHUB_OUTPUT - fi - - if [ -f .github/agentready-dev-logs/adhoc-self-review-summary.txt ]; then - SELF_REVIEW_SUMMARY=$(cat .github/agentready-dev-logs/adhoc-self-review-summary.txt) - echo "self_review_summary<> $GITHUB_OUTPUT - echo "$SELF_REVIEW_SUMMARY" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT - fi - - - name: Post ad-hoc analysis comment - if: steps.issue-context.outputs.is_comment_trigger == 'true' && steps.extract-analysis.outputs.analysis_passed == 'true' - uses: actions/github-script@v8 - env: - LOG_FILE: ${{ steps.init-log.outputs.log_file }} - ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} - ANALYSIS_OUTPUT: ${{ steps.extract-analysis.outputs.analysis }} - SELF_REVIEW_SUMMARY: ${{ steps.extract-analysis.outputs.self_review_summary }} - with: - script: | - const fs = require('fs'); - const issueNumber = parseInt(process.env.ISSUE_NUMBER); - const analysisOutput = process.env.ANALYSIS_OUTPUT; - const selfReviewSummary = process.env.SELF_REVIEW_SUMMARY; - - // Build self-review section - const selfReviewSection = selfReviewSummary && selfReviewSummary !== 'Self-review completed - no changes needed' - ? `\n\n---\n
Self-review results\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
` - : `\n\n---\n
Self-review results\n\nāœ… Analysis verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n
`; - - // Post brief, structured comment - const comment = `šŸ¤– **@agentready-dev Analysis**\n\n${analysisOutput}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: comment, - }); - - // Log activity - const logEntry = { - timestamp: new Date().toISOString(), - agent: 'analysis_agent', - action: 'posted_adhoc_analysis', - issue_number: issueNumber, - }; - fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); - - - name: Upload activity log - if: always() - uses: actions/upload-artifact@v4 - with: - name: agentready-dev-activity-log-${{ github.run_id }} - path: ${{ steps.init-log.outputs.log_file }} - retention-days: 90 - - - name: Summary - if: always() - run: | - if [ "${{ steps.issue-context.outputs.skip_pr_creation }}" == "true" ]; then - echo "## āš ļø Skipped" >> $GITHUB_STEP_SUMMARY - if [ -n "${{ steps.issue-context.outputs.existing_pr_number }}" ]; then - echo "PR already exists for this issue: #${{ steps.issue-context.outputs.existing_pr_number }}" >> $GITHUB_STEP_SUMMARY - else - echo "Issue is already a PR or cannot be processed." >> $GITHUB_STEP_SUMMARY - fi - elif [ "${{ steps.check-review.outputs.final_decision }}" == "provide_feedback" ]; then - echo "## šŸ’¬ Feedback Provided" >> $GITHUB_STEP_SUMMARY - echo "**Issue:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY - echo "Feedback was posted to the issue." >> $GITHUB_STEP_SUMMARY - elif [ "${{ steps.check-review.outputs.final_decision }}" == "create_pr" ]; then - echo "## āœ… Draft PR Created" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**Issue:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY - echo "**Draft PR:** #${{ steps.create-pr.outputs.pr_number }}" >> $GITHUB_STEP_SUMMARY - echo "**URL:** ${{ steps.create-pr.outputs.pr_url }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "The draft PR has been created, reviewed, and linked to the issue." >> $GITHUB_STEP_SUMMARY - elif [ "${{ steps.issue-context.outputs.is_comment_trigger }}" == "true" ]; then - echo "## šŸ” Analysis Complete" >> $GITHUB_STEP_SUMMARY - echo "**Issue/PR:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY - echo "Analysis was posted as a comment." >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY - echo "[View activity log artifact](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/agentready-dev.yml b/.github/workflows/agentready-dev.yml deleted file mode 100644 index e96ade17..00000000 --- a/.github/workflows/agentready-dev.yml +++ /dev/null @@ -1,355 +0,0 @@ -name: Codebase Agent (agentready-dev) - -on: - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - issues: - types: [opened, assigned] - pull_request_review: - types: [submitted] - -permissions: - contents: write - pull-requests: write - issues: write - id-token: write - actions: read - -jobs: - agentready-dev: - # Trigger on @agentready-dev mentions in issues, PRs, and comments - if: | - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@agentready-dev')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@agentready-dev')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@agentready-dev')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@agentready-dev') || contains(github.event.issue.title, '@agentready-dev'))) - runs-on: ubuntu-latest - steps: - - name: Determine event context - id: event-context - run: | - EVENT_NAME="${{ github.event_name }}" - - # Determine if this is a PR-related event and get the PR number - { - if [ "$EVENT_NAME" == "pull_request_review_comment" ]; then - # pull_request_review_comment events have github.event.pull_request - PR_NUMBER="${{ github.event.pull_request.number }}" - echo "is_pr=true" - echo "pr_number=$PR_NUMBER" - echo "issue_number=$PR_NUMBER" - elif [ "$EVENT_NAME" == "pull_request_review" ]; then - # pull_request_review events have github.event.pull_request - PR_NUMBER="${{ github.event.pull_request.number }}" - echo "is_pr=true" - echo "pr_number=$PR_NUMBER" - echo "issue_number=$PR_NUMBER" - elif [ "$EVENT_NAME" == "issue_comment" ]; then - # issue_comment events have github.event.issue - ISSUE_NUMBER="${{ github.event.issue.number }}" - # Check if this issue is actually a PR by checking if pull_request.url exists - # GitHub Actions will return empty string if pull_request doesn't exist - PULL_REQUEST_URL="${{ github.event.issue.pull_request.url || '' }}" - if [ -n "$PULL_REQUEST_URL" ] && [ "$PULL_REQUEST_URL" != "null" ] && [ "$PULL_REQUEST_URL" != "undefined" ]; then - echo "is_pr=true" - echo "pr_number=$ISSUE_NUMBER" - else - echo "is_pr=false" - fi - echo "issue_number=$ISSUE_NUMBER" - elif [ "$EVENT_NAME" == "issues" ]; then - # issues events have github.event.issue - ISSUE_NUMBER="${{ github.event.issue.number }}" - # Check if this issue is actually a PR by checking if pull_request.url exists - # GitHub Actions will return empty string if pull_request doesn't exist - PULL_REQUEST_URL="${{ github.event.issue.pull_request.url || '' }}" - if [ -n "$PULL_REQUEST_URL" ] && [ "$PULL_REQUEST_URL" != "null" ] && [ "$PULL_REQUEST_URL" != "undefined" ]; then - echo "is_pr=true" - echo "pr_number=$ISSUE_NUMBER" - else - echo "is_pr=false" - fi - echo "issue_number=$ISSUE_NUMBER" - else - echo "is_pr=false" - echo "issue_number=" - fi - } >> "$GITHUB_OUTPUT" - - - name: Get PR info for fork support - if: steps.event-context.outputs.is_pr == 'true' - id: pr-info - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPOSITORY: ${{ github.repository }} - PR_NUMBER: ${{ steps.event-context.outputs.pr_number }} - EVENT_NAME: ${{ github.event_name }} - PR_HEAD_SHA_INPUT: ${{ github.event.pull_request.head.sha }} - PR_HEAD_REF_INPUT: ${{ github.event.pull_request.head.ref }} - PR_HEAD_OWNER_INPUT: ${{ github.event.pull_request.head.repo.owner.login }} - PR_HEAD_REPO_INPUT: ${{ github.event.pull_request.head.repo.name }} - PR_HEAD_FORK_INPUT: ${{ github.event.pull_request.head.repo.fork }} - run: | - # For pull_request_review_comment and pull_request_review events, we have direct access - if [ "$EVENT_NAME" == "pull_request_review_comment" ] || [ "$EVENT_NAME" == "pull_request_review" ]; then - PR_HEAD_SHA="$PR_HEAD_SHA_INPUT" - PR_HEAD_REF="$PR_HEAD_REF_INPUT" - PR_HEAD_OWNER="$PR_HEAD_OWNER_INPUT" - PR_HEAD_REPO="$PR_HEAD_REPO_INPUT" - IS_FORK="$PR_HEAD_FORK_INPUT" - else - # For issue_comment and issues events on PRs, fetch from API - PR_DATA=$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER") - PR_HEAD_SHA=$(echo "$PR_DATA" | jq -r '.head.sha') - PR_HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref') - PR_HEAD_OWNER=$(echo "$PR_DATA" | jq -r '.head.repo.owner.login') - PR_HEAD_REPO=$(echo "$PR_DATA" | jq -r '.head.repo.name') - IS_FORK=$(echo "$PR_DATA" | jq -r '.head.repo.fork') - fi - - { - echo "pr_head_owner=$PR_HEAD_OWNER" - echo "pr_head_repo=$PR_HEAD_REPO" - echo "pr_head_ref=$PR_HEAD_REF" - echo "pr_head_sha=$PR_HEAD_SHA" - echo "is_fork=$IS_FORK" - } >> "$GITHUB_OUTPUT" - - - name: Extract user request - id: extract-request - env: - EVENT_NAME: ${{ github.event_name }} - COMMENT_BODY: ${{ github.event.comment.body || '' }} - REVIEW_BODY: ${{ github.event.review.body || '' }} - ISSUE_BODY: ${{ github.event.issue.body || '' }} - ISSUE_TITLE: ${{ github.event.issue.title || '' }} - run: | - case "$EVENT_NAME" in - issue_comment|pull_request_review_comment) - REQUEST="$COMMENT_BODY" - ;; - pull_request_review) - REQUEST="$REVIEW_BODY" - ;; - issues) - # Use body if available, otherwise use title - if [ -n "$ISSUE_BODY" ]; then - REQUEST="$ISSUE_BODY" - else - REQUEST="$ISSUE_TITLE" - fi - ;; - *) - REQUEST="No request body found" - ;; - esac - - # Remove @agentready-dev mention from the request - REQUEST=$(echo "$REQUEST" | sed 's/@agentready-dev//g' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') - - { - echo "request<> "$GITHUB_OUTPUT" - - - name: Determine checkout ref - id: checkout-ref - run: | - if [ "${{ steps.event-context.outputs.is_pr }}" == "true" ]; then - if [ "${{ steps.pr-info.outputs.is_fork }}" == "true" ]; then - # Fork: checkout the fork repository at the PR branch - echo "repository=${{ steps.pr-info.outputs.pr_head_owner }}/${{ steps.pr-info.outputs.pr_head_repo }}" >> "$GITHUB_OUTPUT" - echo "ref=${{ steps.pr-info.outputs.pr_head_ref }}" >> "$GITHUB_OUTPUT" - else - # Same repo PR: checkout at PR head SHA - echo "repository=${{ github.repository }}" >> "$GITHUB_OUTPUT" - echo "ref=${{ steps.pr-info.outputs.pr_head_sha }}" >> "$GITHUB_OUTPUT" - fi - else - # Regular issue: checkout default branch (checkout action will use default if ref is empty) - echo "repository=${{ github.repository }}" >> "$GITHUB_OUTPUT" - # github.ref may not be set for issue events, so leave ref empty to use default branch - if [ -n "${{ github.ref }}" ] && [ "${{ github.ref }}" != "null" ]; then - echo "ref=${{ github.ref }}" >> "$GITHUB_OUTPUT" - fi - # If ref is empty, checkout action will use repository's default branch - fi - - - name: Checkout repository (fork-compatible) - uses: actions/checkout@v6 - with: - repository: ${{ steps.checkout-ref.outputs.repository }} - ref: ${{ steps.checkout-ref.outputs.ref || '' }} - fetch-depth: 0 - - - name: Debug event context - run: | - echo "Event name: ${{ github.event_name }}" - echo "Issue number from step: ${{ steps.event-context.outputs.issue_number }}" - echo "Is PR: ${{ steps.event-context.outputs.is_pr }}" - echo "PR number: ${{ steps.event-context.outputs.pr_number }}" - echo "GitHub context issue: ${{ github.event.issue.number }}" - - - name: Claude Code Action - id: claude-code - uses: anthropics/claude-code-action@v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - prompt: | - You are responding as the @agentready-dev agent. Please analyze the request and post your response as a comment on this issue/PR. - - Request: ${{ steps.extract-request.outputs.request }} - - Important: Make sure to post your response as a comment and clearly indicate you are responding as the @agentready-dev agent. - - - name: Debug event context - run: | - echo "Event name: ${{ github.event_name }}" - echo "Issue number from step: ${{ steps.event-context.outputs.issue_number }}" - echo "Is PR: ${{ steps.event-context.outputs.is_pr }}" - echo "PR number: ${{ steps.event-context.outputs.pr_number }}" - echo "GitHub context issue: ${{ github.event.issue.number }}" - echo "GitHub context issue (alt): ${{ github.event.issue.number || 'not set' }}" - - - name: Post @agentready-dev response - uses: actions/github-script@v8 - env: - ISSUE_NUMBER: ${{ steps.event-context.outputs.issue_number }} - EVENT_NAME: ${{ github.event_name }} - with: - script: | - const issueNumber = process.env.ISSUE_NUMBER; - const eventName = process.env.EVENT_NAME; - console.log('ISSUE_NUMBER from env:', issueNumber); - console.log('EVENT_NAME from env:', eventName); - console.log('Event name from context:', context.eventName); - console.log('Context payload keys:', Object.keys(context.payload || {})); - - // Get the issue/PR number from context - // For issue_comment events, context.issue.number is the most reliable - let targetNumber = issueNumber; - - // Try multiple fallback methods - if (!targetNumber || targetNumber === '' || targetNumber === 'undefined') { - console.log('Trying fallback methods...'); - - // Method 1: context.issue.number (most reliable for issue_comment events) - if (context.issue && context.issue.number) { - targetNumber = context.issue.number; - console.log('Found from context.issue.number:', targetNumber); - } - // Method 2: context.payload.issue.number - else if (context.payload && context.payload.issue && context.payload.issue.number) { - targetNumber = context.payload.issue.number; - console.log('Found from context.payload.issue.number:', targetNumber); - } - // Method 3: context.payload.pull_request.number (for PR comments) - else if (context.payload && context.payload.pull_request && context.payload.pull_request.number) { - targetNumber = context.payload.pull_request.number; - console.log('Found from context.payload.pull_request.number:', targetNumber); - } - // Method 4: Extract from comment issue_url - else if (context.payload && context.payload.comment && context.payload.comment.issue_url) { - const urlParts = context.payload.comment.issue_url.split('/'); - targetNumber = urlParts[urlParts.length - 1]; - console.log('Found from comment.issue_url:', targetNumber); - } - } - - // Convert to number if it's a string - if (targetNumber) { - targetNumber = parseInt(targetNumber, 10); - } - - console.log('Final targetNumber:', targetNumber); - - if (!targetNumber || isNaN(targetNumber)) { - console.log('ERROR: Could not determine issue/PR number'); - console.log('Available context keys:', Object.keys(context)); - console.log('Available payload keys:', Object.keys(context.payload || {})); - throw new Error('Could not determine issue/PR number'); - } - - // Wait a moment for Claude Code Action to post its comment - console.log('Waiting 3 seconds for Claude Code Action to post comment...'); - await new Promise(resolve => setTimeout(resolve, 3000)); - - // Get recent comments - console.log('Fetching comments for issue/PR:', targetNumber); - let comments; - try { - comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: targetNumber, - }); - console.log(`Found ${comments.data.length} total comments`); - } catch (error) { - console.error('Error fetching comments:', error); - throw error; - } - - // Find the most recent comment from github-actions[bot] (Claude Code Action) - const recentComments = comments.data - .filter(comment => { - const commentTime = new Date(comment.created_at); - const twoMinutesAgo = new Date(Date.now() - 2 * 60 * 1000); - return commentTime > twoMinutesAgo; - }) - .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); - - console.log(`Found ${recentComments.length} recent comments (within 2 minutes)`); - - const claudeComment = recentComments.find(comment => - comment.user.login === 'github-actions[bot]' && - !comment.body.includes('@agentready-dev') - ); - - if (claudeComment) { - console.log('Found Claude Code Action comment, updating with attribution...'); - // Update Claude's comment to add @agentready-dev attribution - const updatedBody = `šŸ¤– **Response from @agentready-dev agent:**\n\n---\n\n${claudeComment.body}\n\n---\n*This response was generated by the @agentready-dev workflow.*`; - - try { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: claudeComment.id, - body: updatedBody - }); - console.log('Successfully updated Claude comment with attribution'); - } catch (error) { - console.error('Error updating comment:', error); - throw error; - } - } else { - console.log('No Claude comment found, posting status comment...'); - // If no comment from Claude, post our own status comment - const jobStatus = '${{ job.status }}' === 'success' ? 'āœ…' : 'āŒ'; - const statusText = '${{ job.status }}' === 'success' ? 'completed' : 'failed'; - - const body = `šŸ¤– **@agentready-dev Agent**\n\n` + - `${jobStatus} Analysis ${statusText}.\n\n` + - `The @agentready-dev agent has processed your request. ` + - `Please check the [workflow logs](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${{ github.run_id }}) for details.\n\n` + - `---\n` + - `*This comment was automatically posted by the @agentready-dev workflow.*`; - - try { - const result = await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: targetNumber, - body: body - }); - console.log('Successfully posted comment:', result.data.html_url); - } catch (error) { - console.error('Error creating comment:', error); - console.error('Error details:', JSON.stringify(error, null, 2)); - throw error; - } - } diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 119068db..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Documentation - -on: - pull_request: - branches: - - main - paths: - - 'docs/**' - - '**.md' - - '**.html' - schedule: - # Weekly on Sundays at 2 AM UTC - - cron: '0 2 * * 0' - workflow_dispatch: - -jobs: - link-check: - name: Link Checker - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Install lychee - run: | - curl -sSL https://github.com/lycheeverse/lychee/releases/download/v0.15.1/lychee-v0.15.1-x86_64-unknown-linux-gnu.tar.gz | tar -xz - sudo mv lychee /usr/local/bin/ - lychee --version - - - name: Check links - run: | - lychee --config lychee.toml \ - --no-progress \ - '**/*.md' \ - '**/*.html' \ - --exclude-path '.git' \ - --exclude-path 'node_modules' \ - --exclude-path '.venv' \ - --exclude-path 'docs/_site' diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml deleted file mode 100644 index 059f8ba8..00000000 --- a/.github/workflows/pr-review.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: PR Review - -# Automated code review for pull requests. -# -# Security: Uses pull_request trigger (not pull_request_target) to prevent -# prompt injection attacks. Fork PRs will not receive automated reviews -# since they don't have access to repository secrets. -# -# For fork contributors: Push your branch to the main repo instead of using -# a fork, or request manual review. -# -# Fixes: GitHub #324 (wrong PR context) -# Security: Prevents prompt injection attacks from fork PRs - -on: - pull_request: - types: [opened, synchronize, reopened] - -permissions: - contents: read - pull-requests: write - issues: write - -jobs: - review: - name: Code Review - runs-on: ubuntu-latest - # Skip reviews on fork PRs (no secrets access anyway) - if: github.event.pull_request.head.repo.full_name == github.repository - - steps: - - name: Minimize old Claude review comments - uses: actions/github-script@v8 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - }); - - for (const comment of comments.data) { - if (comment.body.includes('AgentReady Code Review') && - comment.user.login === 'github-actions[bot]') { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id, - body: `
Outdated review (click to expand)\n\n${comment.body}\n
` - }); - } - } - - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Run AgentReady Code Review - uses: anthropics/claude-code-action@v1 - with: - claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - github_token: ${{ secrets.GITHUB_TOKEN }} - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - settings: | - { - "permissions": { - "allow": [ - "Bash(gh pr:*)", - "Bash(gh issue:*)", - "Bash(gh search:*)", - "Bash(git:*)" - ] - } - } - prompt: | - Run the /review-agentready command on pull request #${{ github.event.pull_request.number }}. - - Provide a comprehensive code review focusing on: - - AgentReady attribute compliance - - Security issues - - Code quality - - Best practices - - Post the review as a comment on PR #${{ github.event.pull_request.number }}. diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index 76171eca..f6c717a3 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -18,10 +18,10 @@ jobs: uses: actions/stale@v9 with: # Days before marking as stale - days-before-stale: 21 # 7 days before 28-day close + days-before-stale: 60 # 30 days before 90-day close # Days before closing after marked stale - days-before-close: 7 - # Total: 21 + 7 = 28 days until close + days-before-close: 30 + # Total: 60 + 30 = 90 days until close # Issue labels stale-issue-label: 'stale' @@ -33,7 +33,7 @@ jobs: # Messages stale-issue-message: | - šŸ‘‹ This issue has been inactive for 21 days and will be closed in 7 days if there is no further activity. + šŸ‘‹ This issue has been inactive for 60 days and will be closed in 30 days if there is no further activity. If this issue is still relevant, please: - Add a comment with updates @@ -43,12 +43,12 @@ jobs: Thank you for your contributions to AgentReady! close-issue-message: | - šŸ”’ This issue has been automatically closed due to 28 days of inactivity. + šŸ”’ This issue has been automatically closed due to 90 days of inactivity. If you believe this issue should remain open, please reopen it and provide an update. stale-pr-message: | - šŸ‘‹ This pull request has been inactive for 21 days and will be closed in 7 days if there is no further activity. + šŸ‘‹ This pull request has been inactive for 60 days and will be closed in 30 days if there is no further activity. If you plan to continue work on this PR, please: - Push new commits or add a comment @@ -58,7 +58,7 @@ jobs: Thank you for your contributions to AgentReady! close-pr-message: | - šŸ”’ This pull request has been automatically closed due to 28 days of inactivity. + šŸ”’ This pull request has been automatically closed due to 90 days of inactivity. If you'd like to continue this work, please reopen the PR or create a new one.