Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,31 @@ Agent instruction files live in `.github/agents/`:
- `maintainer-upgrade.md` — how to apply caretaker upgrades

Always check these files when you receive a caretaker assignment.

<!-- Added by caretaker -->

## Caretaker System

This repository uses the caretaker automated management system.

### How it works

- An orchestrator runs weekly via GitHub Actions
- It creates issues and assigns them to @copilot for execution
- When @copilot opens PRs, the orchestrator monitors them through CI, review, and merge
- The orchestrator communicates with @copilot via structured issue/PR comments

### When assigned an issue by caretaker

- Read the full issue body carefully — it contains structured instructions
- Follow the instructions exactly as written
- If unclear, comment on the issue asking for clarification
- Always ensure CI passes before considering work complete
- Reference the agent file for your role: `.github/agents/maintainer-pr.md` or `maintainer-issue.md`

### Conventions

- Branch naming: `maintainer/{type}-{description}`
- Commit messages: `chore(maintainer): {description}`
- Always run existing tests before pushing
- Do not modify `.github/maintainer/` files unless explicitly instructed
109 changes: 109 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Claude Code Review (gated)

# DORMANT BY DEFAULT — this workflow does NOT auto-run on PR open/push.
#
# It fires only when something explicitly triggers it:
# 1. Caretaker applies the ``claude-code`` label (happens when
# ``pr_reviewer.complex_reviewer = "claude_code"`` in caretaker
# config and a complex PR is dispatched).
# 2. A human applies the same label manually.
# 3. A human runs the workflow from the Actions tab (workflow_dispatch).
#
# To prefer the in-pod opencode_local backend (no consumer-side workflow
# at all), set in ``.github/maintainer/config.yml``:
#
# pr_reviewer:
# complex_reviewer: opencode_local
# enabled_backends: [claude_code, opencode, opencode_local, pr_agent]
#
# and never apply the ``claude-code`` label. This workflow stays
# present as a fallback / opt-in path; the backend is the default.

on:
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
pr_number:
description: "PR number to review"
required: true
type: number

jobs:
claude-review:
# Only run when the claude-code label was just applied, or when
# the workflow was dispatched manually.
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.label.name == 'claude-code')

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Resolve PR number
id: pr
run: |
if [ -n "${{ github.event.pull_request.number }}" ]; then
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
else
echo "number=${{ inputs.pr_number }}" >> "$GITHUB_OUTPUT"
fi

- name: Preflight — check Claude OAuth token availability
id: preflight
env:
OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
run: |
if [ -z "$OAUTH_TOKEN" ]; then
echo "::warning::CLAUDE_CODE_OAUTH_TOKEN is not set — falling back to Copilot review"
echo "claude_available=false" >> "$GITHUB_OUTPUT"
else
echo "claude_available=true" >> "$GITHUB_OUTPUT"
fi

- name: Run Claude Code Review
id: claude-review
if: steps.preflight.outputs.claude_available == 'true'
continue-on-error: true
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ steps.pr.outputs.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

- name: Fallback — request Copilot review
if: |
steps.preflight.outputs.claude_available != 'true' ||
steps.claude-review.outcome == 'failure'
uses: actions/github-script@v7
with:
script: |
const prNumber = parseInt('${{ steps.pr.outputs.number }}', 10);
const reason = '${{ steps.preflight.outputs.claude_available }}' === 'true'
? 'Claude review action failed'
: 'Claude OAuth token unavailable';
core.info(`${reason} — requesting Copilot review for PR #${prNumber}`);
try {
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
reviewers: ['copilot-pull-request-reviewer'],
});
core.info(`Requested Copilot review for PR #${prNumber}`);
} catch (error) {
core.warning(`Copilot review request failed: ${error.message}`);
}
119 changes: 119 additions & 0 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: opencode Review (gated)

# DORMANT BY DEFAULT — this workflow does NOT auto-run on PR open/push.
#
# It fires only when something explicitly triggers it:
# 1. Caretaker applies the ``opencode-review`` label (happens when
# ``pr_reviewer.complex_reviewer = "opencode"`` in caretaker config
# and a complex PR is dispatched).
# 2. A human applies the same label manually.
# 3. A human runs the workflow from the Actions tab (workflow_dispatch).
#
# To prefer the in-pod opencode_local backend (no consumer-side workflow
# at all), set in ``.github/maintainer/config.yml``:
#
# pr_reviewer:
# complex_reviewer: opencode_local
# enabled_backends: [claude_code, opencode, opencode_local, pr_agent]
#
# and never apply the ``opencode-review`` label. This workflow stays
# present as a fallback / opt-in path; the backend is the default.

on:
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
pr_number:
description: "PR number to review"
required: true
type: number

jobs:
opencode-review:
# Only run when the opencode-review label was just applied, or
# when the workflow was dispatched manually.
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.label.name == 'opencode-review')

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Resolve PR number
id: pr
run: |
if [ -n "${{ github.event.pull_request.number }}" ]; then
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
else
echo "number=${{ inputs.pr_number }}" >> "$GITHUB_OUTPUT"
fi

- name: Preflight — check opencode provider keys are available
id: preflight
env:
ANTHROPIC_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENROUTER_KEY: ${{ secrets.OPENROUTER_API_KEY }}
GROQ_KEY: ${{ secrets.GROQ_API_KEY }}
run: |
if [ -z "$ANTHROPIC_KEY" ] && [ -z "$OPENAI_KEY" ] && [ -z "$OPENROUTER_KEY" ] && [ -z "$GROQ_KEY" ]; then
echo "::warning::No opencode provider key set — falling back to Copilot review"
echo "opencode_available=false" >> "$GITHUB_OUTPUT"
else
echo "opencode_available=true" >> "$GITHUB_OUTPUT"
fi

- name: Run opencode review
id: opencode-review
if: steps.preflight.outputs.opencode_available == 'true'
continue-on-error: true
# Pinning to ``@latest`` is convenient but a supply-chain risk.
# Pin to a specific tag (``sst/opencode/github@v0.1.0``) or
# commit SHA before relying on this in production.
uses: sst/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
with:
model: anthropic/claude-sonnet-4
prompt: |
Review pull request ${{ github.repository }}#${{ steps.pr.outputs.number }}.
Focus on correctness, security, API contracts, and missing tests.
Post a review comment summary and inline comments where applicable.

- name: Fallback — request Copilot review
if: |
steps.preflight.outputs.opencode_available != 'true' ||
steps.opencode-review.outcome == 'failure'
uses: actions/github-script@v7
with:
script: |
const prNumber = parseInt('${{ steps.pr.outputs.number }}', 10);
const reason = '${{ steps.preflight.outputs.opencode_available }}' === 'true'
? 'opencode review action failed'
: 'opencode provider keys unavailable';
core.info(`${reason} — requesting Copilot review for PR #${prNumber}`);
try {
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
reviewers: ['copilot-pull-request-reviewer'],
});
core.info(`Requested Copilot review for PR #${prNumber}`);
} catch (error) {
core.warning(`Copilot review request failed: ${error.message}`);
}
Loading