Skip to content

[FEATURE] Configuration file-based ACL for /agentready assess command #27

[FEATURE] Configuration file-based ACL for /agentready assess command

[FEATURE] Configuration file-based ACL for /agentready assess command #27

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: 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 }}
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<<EOF" >> $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 }}
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<<EOF" >> $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<details><summary>Self-review results</summary>\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</details>`
: `\n\n---\n<details><summary>Self-review results</summary>\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</details>`;
// 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 }}
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 }}
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<<EOF" >> $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<<EOF" >> $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<details><summary>Self-review results</summary>\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>`
: `\n\n---\n<details><summary>Self-review results</summary>\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</details>`;
// 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 }}
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 }}
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<<EOF" >> $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<<EOF" >> $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<details><summary>Self-review results</summary>\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>`
: `\n\n---\n<details><summary>Self-review results</summary>\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</details>`;
// 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