Compare commits

..

2 Commits

Author SHA1 Message Date
peptiderepo
9056eb4df6 ci: post CTO review as COMMENT instead of APPROVE
GITHUB_TOKEN cannot formally approve PRs without a repo setting toggle.
Verdict is still prominent in the first line of the review body, and
the human merges based on reading it — no behavior loss.

Agent-Session: cowork-reviewer-fix-20260414
2026-04-14 16:51:51 +07:00
peptiderepo
48f3119820 ci: add review gate (tripwire audit + Claude auto-review via OpenRouter) (#1)
* ci: add main-push audit tripwire

Flags direct pushes to main that did not come from a merged PR.
Free-plan workaround since branch protection requires GitHub Pro.

* docs: add Git Workflow section to CONVENTIONS.md

Documents the PR-gated review process enforced at the agent layer.
Free-plan workaround since branch protection requires GitHub Pro.

* ci: add Claude-powered CTO PR review workflow

Auto-reviews every PR with Claude Haiku 4.5 and posts a structured
review (APPROVE / REQUEST_CHANGES / COMMENT). Does NOT auto-merge — a
human still clicks Merge. Requires ANTHROPIC_API_KEY secret on the repo.

* ci: switch CTO reviewer from Anthropic direct to OpenRouter

Reuses the OPENROUTER_API_KEY secret that already backs the other AI
plugins. Consolidates AI spend on one bill. Model: anthropic/claude-haiku-4.5.
2026-04-14 16:45:47 +07:00

View File

@@ -224,25 +224,22 @@ jobs:
PY PY
- name: Post PR review - name: Post PR review
# Always posts as COMMENT — not APPROVE/REQUEST_CHANGES — because the default
# GITHUB_TOKEN is not permitted to formally approve PRs without toggling a
# repo setting. The verdict is still prominent in the first line of the body
# ("## CTO Review — APPROVE|REQUEST_CHANGES|COMMENT"). Human merges, so the
# GitHub-native review state isn't load-bearing.
if: steps.claude.outputs.skipped != '1' if: steps.claude.outputs.skipped != '1'
uses: actions/github-script@v7 uses: actions/github-script@v7
env:
VERDICT: ${{ steps.claude.outputs.verdict }}
with: with:
script: | script: |
const fs = require('fs'); const fs = require('fs');
const body = fs.readFileSync('/tmp/review-body.md', 'utf8'); const body = fs.readFileSync('/tmp/review-body.md', 'utf8');
const verdict = process.env.VERDICT;
const eventMap = {
'APPROVE': 'APPROVE',
'REQUEST_CHANGES': 'REQUEST_CHANGES',
'COMMENT': 'COMMENT'
};
await github.rest.pulls.createReview({ await github.rest.pulls.createReview({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
pull_number: context.issue.number, pull_number: context.issue.number,
event: eventMap[verdict] || 'COMMENT', event: 'COMMENT',
body, body,
}); });