Compare commits

..

4 Commits

Author SHA1 Message Date
peptiderepo
49138541d0 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:05 +07:00
peptiderepo
7b9d8b3676 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.
2026-04-14 15:57:20 +07:00
peptiderepo
efd60947be 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.
2026-04-14 15:53:35 +07:00
peptiderepo
2d7ece8a0e 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.
2026-04-14 15:45:07 +07:00
2 changed files with 98 additions and 100 deletions

View File

@@ -224,22 +224,25 @@ jobs:
PY
- 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'
uses: actions/github-script@v7
env:
VERDICT: ${{ steps.claude.outputs.verdict }}
with:
script: |
const fs = require('fs');
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({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
event: 'COMMENT',
event: eventMap[verdict] || 'COMMENT',
body,
});

View File

@@ -45,12 +45,7 @@ jobs:
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
# Best-effort: keyscan stderr captured for diagnosis but never fatal.
# We use StrictHostKeyChecking=no on the actual ssh/rsync calls anyway.
ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/tmp/keyscan.err || {
echo "::warning::ssh-keyscan failed (non-fatal). stderr:"
cat /tmp/keyscan.err || true
}
ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
- name: Deploy via rsync
run: |