askill
approval-checker

approval-checkerSafety 100Repository

Verifies that an authorized user has approved the fix plan before proceeding with implementation.

0 stars
1.2k downloads
Updated 1/27/2026

Package Files

Loading files...
SKILL.md

Purpose

Check for:

  1. Thumbs-up (πŸ‘) reaction on plan comment
  2. "Approve" keyword in reply comments
  3. User is authorized (maintainer/admin)

Only authorized approvals count - ignore others safely.

Usage

Include this file when checking approval:

Use lib/approval-checker to verify approval before implementing

Authorization

Who Can Approve?

Users with push or admin permissions on the repository.

gh api repos/{owner}/{repo}/collaborators \
  --jq '[.[] | select(.permissions.push == true or .permissions.admin == true) | .login]'

Example output:

["alice", "bob", "charlie"]

These are the authorized approvers.

Why This Matters

Security: Prevents unauthorized code changes.

Scenario:

  • External contributor comments "approve" β†’ Ignored (not authorized)
  • Repository maintainer clicks πŸ‘ β†’ Accepted (authorized)

Approval Methods

Method 1: Thumbs Up Reaction (πŸ‘)

User clicks thumbs-up on the plan comment.

Check:

# Get plan comment ID from previous step
COMMENT_ID=<plan-comment-id>

# Fetch reactions
gh api repos/{owner}/{repo}/issues/comments/${COMMENT_ID}/reactions \
  --jq '.[] | select(.content == "+1") | .user.login'

Output: List of usernames who reacted with πŸ‘

Logic:

reactions = get_thumbs_up_reactions(comment_id)
authorized = get_authorized_users()

for user in reactions:
    if user in authorized:
        return {"approved": True, "approver": user, "method": "reaction"}

return {"approved": False}

Method 2: Approval Comment

User replies with "approve", "approved", "lgtm", or "go ahead" (case-insensitive).

Check:

# Get all comments after the plan was posted
PLAN_TIMESTAMP="2026-01-16T10:00:00Z"

gh issue view <issue-number> --json comments \
  --jq '.comments[] | select(.createdAt > "'$PLAN_TIMESTAMP'") | {author: .author.login, body: .body}'

Output: Recent comments with author and body

Logic:

import re

approval_keywords = ["approve", "approved", "lgtm", "go ahead"]
pattern = re.compile(r'\b(' + '|'.join(approval_keywords) + r')\b', re.IGNORECASE)

comments = get_comments_after(plan_timestamp)
authorized = get_authorized_users()

for comment in comments:
    if comment.author in authorized:
        if pattern.search(comment.body):
            return {"approved": True, "approver": comment.author, "method": "comment"}

return {"approved": False}

Implementation Steps

Step 1: Get Repository Info

# Extract owner and repo from git remote
REMOTE=$(git remote get-url origin)
# Parse: https://github.com/owner/repo.git or git@github.com:owner/repo.git

OWNER=$(echo $REMOTE | sed -E 's/.*github\.com[:/]([^/]+).*/\1/')
REPO=$(echo $REMOTE | sed -E 's/.*github\.com[:/][^/]+\/([^.]+).*/\1/')

Step 2: Get Authorized Users

gh api repos/${OWNER}/${REPO}/collaborators \
  --jq '[.[] | select(.permissions.push == true or .permissions.admin == true) | .login]' \
  > /tmp/authorized_users.json

Step 3: Find Plan Comment

gh issue view <issue-number> --json comments \
  --jq '.comments[] | select(.body | contains("πŸ€– Automated Fix Plan")) | {id: .id, createdAt: .createdAt}'

Output:

{
  "id": "IC_kwDOA...",
  "createdAt": "2026-01-16T10:00:00Z"
}

Step 4: Check Method 1 (Reactions)

COMMENT_ID="IC_kwDOA..."

gh api repos/${OWNER}/${REPO}/issues/comments/${COMMENT_ID}/reactions \
  --jq '.[] | select(.content == "+1") | .user.login' \
  > /tmp/reactions.txt

Check if any reactor is in authorized users:

while read user; do
  if grep -q "\"$user\"" /tmp/authorized_users.json; then
    echo "APPROVED by $user via reaction"
    exit 0
  fi
done < /tmp/reactions.txt

Step 5: Check Method 2 (Comments)

PLAN_TIMESTAMP="2026-01-16T10:00:00Z"

gh issue view <issue-number> --json comments \
  --jq '.comments[] | select(.createdAt > "'$PLAN_TIMESTAMP'") | {author: .author.login, body: .body}' \
  > /tmp/recent_comments.json

Check for approval keywords from authorized users:

jq -r '.[] | "\(.author)|\(.body)"' /tmp/recent_comments.json | while IFS='|' read author body; do
  # Check if author is authorized
  if grep -q "\"$author\"" /tmp/authorized_users.json; then
    # Check for approval keywords (case-insensitive)
    if echo "$body" | grep -iE '\b(approve|approved|lgtm|go ahead)\b' > /dev/null; then
      echo "APPROVED by $author via comment"
      exit 0
    fi
  fi
done

Step 6: Not Approved Response

If no approval found after checking both methods:

gh issue comment <issue-number> --body "⚠️ **Approval Required**

No approval detected yet. To proceed:
- πŸ‘ Add thumbs up reaction to the plan comment above, OR
- πŸ’¬ Reply with 'approve' or 'lgtm'

Note: Only repository maintainers can approve.

Current authorized approvers: $(cat /tmp/authorized_users.json | jq -r '.[] | "@" + .')"

Example output:

⚠️ **Approval Required**

No approval detected yet. To proceed:
- πŸ‘ Add thumbs up reaction to the plan comment above, OR
- πŸ’¬ Reply with 'approve' or 'lgtm'

Note: Only repository maintainers can approve.

Current authorized approvers: @alice @bob @charlie

Output Format

Return approval status:

{
  "approved": true,
  "approver": "alice",
  "method": "reaction",
  "timestamp": "2026-01-16T10:05:00Z"
}

Or:

{
  "approved": false,
  "reason": "No approval from authorized users",
  "authorized_users": ["alice", "bob", "charlie"]
}

Error Handling

GitHub API Error

gh api repos/${OWNER}/${REPO}/collaborators 2>&1

If fails:

⚠️ **Approval Check Failed**

Couldn't verify approval due to API error:
\`\`\`
<error message>
\`\`\`

**Troubleshooting:**
1. Check GitHub CLI authentication: \`gh auth status\`
2. Verify repository access: \`gh repo view ${OWNER}/${REPO}\`
3. Try again: \`/continue-issue <issue-number>\`

If error persists, you can implement the plan manually.

Plan Comment Not Found

⚠️ **Plan Comment Not Found**

Couldn't find the automated fix plan comment on this issue.

Did you run \`/handle-issue <issue-number>\` first?

**To proceed:**
1. Run \`/handle-issue <issue-number>\` to generate plan
2. Review and approve the plan
3. Run \`/continue-issue <issue-number>\`

Multiple Approvals

If multiple authorized users approve:

# Use first approval found (earliest timestamp)
approvals.sort(key=lambda x: x.timestamp)
return approvals[0]

Integration with continue-issue

1. Parse issue number
2. Check approval (lib/approval-checker) ← YOU ARE HERE
3. If approved β†’ Create worktree β†’ Implement
4. If not approved β†’ Post helpful message β†’ Exit

Flow:

/continue-issue 42
    ↓
Get authorized users from GitHub
    ↓
Find plan comment
    ↓
Check reactions (Method 1)
    ↓
    β”œβ”€ Approved β†’ Proceed
    └─ Not approved
        ↓
    Check comments (Method 2)
        ↓
        β”œβ”€ Approved β†’ Proceed
        └─ Not approved β†’ Post message β†’ Exit

Security Considerations

No bypass mechanisms:

  • Can't override with flags
  • Can't skip check
  • Can't fake authorization

Safe handling of unknowns:

  • Unknown users β†’ Ignored
  • Partial approval β†’ Not sufficient
  • Ambiguous comments β†’ Not approved

Principle: Fail closed, not open.

Testing Approach

Test cases:

  1. βœ… Authorized user reacts πŸ‘ β†’ Approved
  2. βœ… Authorized user comments "approve" β†’ Approved
  3. βœ… Authorized user comments "LGTM" β†’ Approved
  4. ❌ Unauthorized user reacts πŸ‘ β†’ Not approved
  5. ❌ Unauthorized user comments "approve" β†’ Not approved
  6. ❌ Authorized user comments "looks good" β†’ Not approved (no keyword)
  7. βœ… Multiple approvals β†’ Use first one
  8. ❌ GitHub API error β†’ Fail gracefully with message

YAGNI Notes

Not included:

  • Multi-level approval (single maintainer sufficient)
  • Approval expiration (valid until revoked)
  • Approval delegation (direct authorization only)
  • Vote counting (single approval sufficient)

Keep it simple: one authorized approval proceeds.

Install

Download ZIP
Requires askill CLI v1.0+β–Ά

AI Quality Score

96/100Analyzed 2/10/2026

An exceptionally well-documented skill for implementing an approval gate in GitHub-based automation. It provides precise shell commands, logic flows, and robust error handling strategies.

100
100
85
100
95

Metadata

Licenseunknown
Version-
Updated1/27/2026
PublisherJuniYadi

Tags

apigithubsecuritytesting