diff --git a/.github/workflows/wizrd-agent.yml b/.github/workflows/wizrd-agent.yml new file mode 100644 index 0000000..1bba873 --- /dev/null +++ b/.github/workflows/wizrd-agent.yml @@ -0,0 +1,97 @@ +name: Wizrd Agent + +on: + workflow_call: + inputs: + base_branch: + description: 'Base branch for PRs Claude creates.' + required: false + type: string + default: 'main' + branch_prefix: + description: 'Prefix for branches Claude creates.' + required: false + type: string + default: 'feat/' + branch_name_template: + description: 'Branch naming template.' + required: false + type: string + default: '{{prefix}}{{description}}' + secrets: + claude_token: + description: 'CLAUDE_CODE_OAUTH_TOKEN' + required: true + +jobs: + agent: + name: agent + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + id-token: write + actions: read + steps: + - name: Remove ai:implement label (if present) + if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'ai: implement' + uses: actions/github-script@v7 + with: + script: | + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + name: 'ai: implement', + }); + } catch (e) { + core.info(`Could not remove label: ${e.message}`); + } + + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Discover agent context + id: discover + shell: bash + run: | + set -e + for candidate in .claude/ci-agent-context.md .claude/agent-context.md CLAUDE.md; do + if [ -f "$candidate" ]; then echo "agent=$candidate" >> "$GITHUB_OUTPUT"; break; fi + done + + - name: Load agent instructions into env + if: steps.discover.outputs.agent != '' + shell: bash + run: | + { + echo 'INSTRUCTIONS<> "$GITHUB_ENV" + + - name: Run Claude Code (with context) + if: steps.discover.outputs.agent != '' + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.claude_token }} + base_branch: ${{ inputs.base_branch }} + branch_prefix: ${{ inputs.branch_prefix }} + branch_name_template: ${{ inputs.branch_name_template }} + additional_permissions: | + actions: read + claude_args: '--append-system-prompt "${{ env.INSTRUCTIONS }}"' + + - name: Run Claude Code (no context) + if: steps.discover.outputs.agent == '' + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.claude_token }} + base_branch: ${{ inputs.base_branch }} + branch_prefix: ${{ inputs.branch_prefix }} + branch_name_template: ${{ inputs.branch_name_template }} + additional_permissions: | + actions: read diff --git a/.github/workflows/wizrd-review.yml b/.github/workflows/wizrd-review.yml new file mode 100644 index 0000000..a93fbee --- /dev/null +++ b/.github/workflows/wizrd-review.yml @@ -0,0 +1,61 @@ +name: Wizrd Review + +on: + workflow_call: + inputs: + review_style: + description: 'concise | thorough — appended to the plugin prompt as guidance.' + required: false + type: string + default: 'concise' + extra_instructions: + description: 'Optional extra prompt text appended after the plugin invocation (e.g. point at REVIEW_RULES.md / CLAUDE.md).' + required: false + type: string + default: '' + secrets: + claude_token: + description: 'CLAUDE_CODE_OAUTH_TOKEN' + required: true + +jobs: + review: + name: review + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + issues: read + id-token: write + actions: read + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 1 + + - uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.claude_token }} + plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' + plugins: 'code-review@claude-code-plugins' + prompt: | + /code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} + + Review style: ${{ inputs.review_style }}. + + Before reviewing, read these if present (auto-discovery order): + REVIEW_RULES.md → CODE_REVIEW.md → CLAUDE.md → .claude/ci-agent-context.md. + Apply rule codes from REVIEW_RULES.md if it uses them (B/R/A). Otherwise apply + standard senior-engineer judgement: correctness, security, simplicity, tests. + + Categorise findings: + 🔴 BLOCKING (must fix before merge) + 🟡 REQUIRED (should fix before merge) + 🟢 ADVISORY (reviewer discretion) + ✅ What's Good (2-3 specific things) + + Be concise. Cite `file:line` for every code finding. Group repeated patterns. + Skip auto-generated files, lockfiles, migration boilerplate. + + ${{ inputs.extra_instructions }} diff --git a/.github/workflows/wizrd-validate.yml b/.github/workflows/wizrd-validate.yml new file mode 100644 index 0000000..8b1234e --- /dev/null +++ b/.github/workflows/wizrd-validate.yml @@ -0,0 +1,54 @@ +name: Wizrd Validate + +on: + workflow_call: + inputs: + level: + description: 'L0 | L1 | L2 (auto-detected from CLAUDE.md if empty)' + required: false + type: string + default: '' + ref: + description: 'wizrd-cli ref (default: v1 — pin to v1.x.y for stability)' + required: false + type: string + default: 'v1' + +jobs: + validate: + name: validate + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout caller repo + uses: actions/checkout@v5 + with: + fetch-depth: 0 + submodules: false + + - name: Checkout wizrd-cli + uses: actions/checkout@v5 + with: + repository: Digitaliko/wizrd-cli + ref: ${{ inputs.ref }} + token: ${{ github.token }} + path: .wizrd-cli + + - name: Run validate + shell: bash + run: | + chmod +x .wizrd-cli/validate/validate.sh .wizrd-cli/validate/lib/*.sh .wizrd-cli/validate/checks/*.sh + set +e + bash .wizrd-cli/validate/validate.sh --ci + EXIT_CODE=$? + set -e + if [ "$EXIT_CODE" -eq 2 ]; then + echo "::error::Wizrd validation failed with critical issues" + exit 1 + elif [ "$EXIT_CODE" -eq 1 ]; then + echo "::warning::Wizrd validation passed with warnings" + fi + env: + WIZRD_LEVEL: ${{ inputs.level }} + WIZRD_REPO_ROOT: ${{ github.workspace }}