feat(ci): ClawReview π¦ β our own advisory PR bot (policy + duplicates + review)#248
Conversation
β¦ review) Clawsweeper-inspired PR bot, owned by us, complementing CodeRabbit: - Structured advisory review on every PR (opened/reopened/synchronize): summary, source/test surface split, severity-ranked findings (P1-P3), duplicate detection vs open PRs + linked-issue validation, and a hidden <!-- clawreview-verdict:... --> marker for tooling - Deterministic repo-policy checks (no AI needed): beta-first base-branch rule (docs/meta paths may target main), package.json<->bun.lock consistency, conventional title, tests-expected heuristic, security-sensitive-path flagging, size warning - Auto area-labels from touched paths (same taxonomy as the issue-triage bot) - Advisory by design: posts + updates ONE comment (upsert by marker, no spam on every push); never closes PRs; never fails the pipeline (exit 0 on any error); skips bot-authored PRs - Security: pull_request_target with the base-repo checkout ONLY β PR code is never checked out or executed; the diff is reviewed as data via the API (capped at 80k chars); PR title/body/diff are declared untrusted in the system prompt - Same hardening as the triage bot: SHA-pinned actions, job-scoped permissions, --prefix scripts SDK install, graceful no-op without ANTHROPIC_API_KEY (same pending secret) Dry-run validated against real PRs: ID-Robots#243 (bot-skip fires), ID-Robots#238 (meta->main passes base policy), ID-Robots#227 (device->beta passes; sensitive-path + tests checks fire).
β¦d plumbing Four-angle /simplify review applied. The big one: replaying the policy checks against the 40 most recently merged PRs showed 55% would have warned (the routine release PR collected 5 warnings at once) β warnings tuned to be rare enough to mean something: - Release promotions (head beta -> base main) are the sanctioned path to main: exempted from feature-PR conventions (was 3/4 of base-check warns) - Lockfile check is diff-aware: only warns when package.json DEPENDENCY sections change β version-only bumps never break --frozen-lockfile (6/6 historical warns on the naive check were false) - 'release' added to the conventional-title types (the repo's own release convention was failing its own check) - Tests-expected check gated to >=10 changed src lines (string-swap PRs were the main noise) - SENSITIVE_RE: config/ narrowed to root-privilege files (was flagging every openclaw-target.txt version bump); added real misses (login-api route, rate limiters, oauth utils, credentials route, root-update-step.sh, launch-browser.sh, recover.sh); rendered as an βΉοΈ note, notβ οΈ , so warnings keep meaning Plumbing (config + simplification reviews): - upsertComment author-checked (a user comment starting with our marker can't be PATCH-overwritten) and single-page (bot comments early) - --paginate + per-page '-q [...]' arrays would crash JSON.parse on >100-item PRs (we've had a 1,028-file PR) β files now fetched as JSONL - drafts skipped (reviewed at ready_for_review; type added) - bot-skip moved before the expensive gathering; dead 'dependabot' arm dropped; dead fetched fields trimmed; labels applied in one batched pr edit; duplicate render gated on likely && of - reciprocal keep-in-sync comments at the two cross-bot drift points (area taxonomy, SDK version pin) Re-validated by dry-run: ID-Robots#217 release promotion 5 warns -> 0 (1 pass + 1 info), ID-Robots#238 meta->main all-pass, ID-Robots#227 device->beta all-pass.
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review detailsβοΈ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: π Files selected for processing (4)
π WalkthroughWalkthroughThis PR adds a new "ClawReview" GitHub Actions workflow and accompanying ChangesClawReview PR advisory bot
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Contributor
participant GitHub
participant ClawReviewWorkflow
participant PRReviewScript
participant AnthropicAPI
Contributor->>GitHub: open/update pull request
GitHub->>ClawReviewWorkflow: pull_request_target event
ClawReviewWorkflow->>ClawReviewWorkflow: skip if bot-authored or draft
ClawReviewWorkflow->>PRReviewScript: run node scripts/pr-review.mjs
PRReviewScript->>GitHub: fetch PR metadata, diff, linked issues, open PRs
PRReviewScript->>PRReviewScript: run deterministic policy checks
PRReviewScript->>AnthropicAPI: request structured review JSON
AnthropicAPI-->>PRReviewScript: summary, findings, duplicate verdict
PRReviewScript->>GitHub: upsert marked comment
PRReviewScript->>GitHub: apply up to 3 area labels
Possibly related PRs
Suggested reviewers: π₯ Pre-merge checks | β 4 | β 1β Failed checks (1 warning)
β Passed checks (4 passed)
β¨ Finishing Touchesπ§ͺ Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/pr-review.yml:
- Around line 11-30: Add a workflow-level permissions block at the top of the
pr-review workflow so the default GITHUB_TOKEN starts with no access; keep the
existing job-scoped permissions on the review job unchanged. Update the
top-level workflow configuration near the pull_request_target and jobs
definitions so only the explicit review job scopes apply and the default grant
is empty.
In `@scripts/pr-review.mjs`:
- Around line 110-114: The `bun.lock` warning logic in `scripts/pr-review.mjs`
is too broad because the `depsTouched` scan inside the `package.json` hunk
treats any added/removed top-level string property as a dependency change.
Tighten the check in the `package.json` branch so it only flags actual
dependency sections, using the existing `depsTouched`/`warn` flow and `hunk`
scan logic; either track the current top-level key while iterating the hunk or
explicitly exclude non-dependency keys like `name`, `description`, `scripts`,
`author`, and `version` before calling `warn`.
πͺ Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
βΉοΈ Review info
βοΈ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: d74e9b93-dad8-48a8-8269-ed645719b6e3
π Files selected for processing (5)
.github/workflows/issue-triage.yml.github/workflows/pr-review.ymlCONTRIBUTING.mdscripts/issue-triage.mjsscripts/pr-review.mjs
Playful frame, rigorous content: greeting, verdict badge, clean-bill line, and sign-off carry the persona (Shipshape β claws up / Needs a molt / Walking sideways / This shell looks occupied); policy checks and findings stay strictly factual so a P1 never drowns in puns. Lines are picked deterministically by PR number, keeping the upserted comment's voice stable across pushes. The model's summary gets at most one marine flourish by prompt; finding titles/details are instructed pun-free.
β¦crab avatar) Both bots (pr-review + issue-triage) mint an installation token via actions/create-github-app-token when the CLAWREVIEW_APP_ID + CLAWREVIEW_APP_PRIVATE_KEY secrets exist β comments and labels then post as clawreview[bot] with the App's avatar (and get the App's own rate limits). Without the secrets the step skips and everything falls back to github-actions[bot]; the bots work either way. Comment-upsert author check accepts both identities so the switch-over edits the same comment.
Both bots now prefer the Claude Code CLI (claude -p, authed by CLAUDE_CODE_OAUTH_TOKEN) β the official Pro/Max subscription path, same runtime as claude-code-action and the team's crons β falling back to the Anthropic SDK when only ANTHROPIC_API_KEY is set, and no-op without either. - review()/main() split into reviewViaClaudeCli + reviewViaSdk (pr-review) and classifyViaClaudeCli + classifyViaSdk (issue-triage); selected by CLAUDE_CODE_OAUTH_TOKEN presence at runtime - parseModelJson tolerates fenced/wrapped CLI output (json wrapper -> .result -> object); the SDK path keeps schema-enforced output - workflows install the backend the available secret needs (CLI when OAuth, SDK otherwise), both pinned; token passed to the run step - REVIEW_ONLY env prints the composed comment without posting, for local end-to-end testing of either transport CodeRabbit (ID-Robots#248): - top-level permissions: {} so the default token grant is empty (only the job's explicit scopes apply) - bun.lock check: dependency-entry match now requires a version-spec-shaped value (^/~/digit/npm:/workspace:/git/url), so edits to scripts/name/etc. no longer misfire the 'dependencies changed' warning Validated end-to-end via the OAuth CLI transport against PR ID-Robots#227: correct verdict, crab voice, and a genuine P3 finding in gateway-pre-start.sh.
β¦#252) * fix(ci): lazy-load the Anthropic SDK so the OAuth path needs no SDK The OAuth transport (shipped in #248) installs only the Claude Code CLI, not @anthropic-ai/sdk, but both bot scripts had a static top-level 'import Anthropic from @anthropic-ai/sdk' evaluated at module load regardless of transport β so the live bots on main crash with ERR_MODULE_NOT_FOUND before running. Moved the import into a dynamic import() inside reviewViaSdk/classifyViaSdk, reached only on the API-key fallback. Verified by running the OAuth path with node_modules removed. Same fix rides to beta in #250. * feat(ci): reshape ClawReview into an informative mascot (not a reviewer) Per direction: ClawReview should be a knowledgeable, friendly crab mascot that greets and orients on issues/PRs β NOT a code reviewer racing CodeRabbit. PR bot (pr-review.mjs): - Dropped severity findings (P1/P2/P3) and pass/fail verdicts β that was the CodeRabbit-racing part. Schema is now summary + kind + touches + neutral 'highlights' (helpful heads-ups, never bug reports) + duplicate hint. - System prompt recast: 'you are the mascot, not a reviewer; CodeRabbit does the line-by-line; produce orientation, never verdicts'. Empty highlights is normal and encouraged. - Comment is now: greeting -> plain-language summary -> 'At a glance' (kind/touches/base/surface + deterministic policy heads-ups) -> optional 'Good to know' -> sign-off that explicitly defers to CodeRabbit. Issue bot (issue-triage.mjs): - Rebranded the triage comment as the same crab mascot (one character across issues + PRs): friendly greeting + summary + at-a-glance labels + next step. - Added DRY_RUN (prints the comment, skips label writes) for local testing. Deterministic policy checks stay β they're genuine ClawBox-specific value (beta-first, bun.lock, sensitive paths) CodeRabbit can't provide β but are now framed as friendly context, not a verdict. Validated end-to-end via the OAuth CLI transport on PR #227 and issue #232. * chore(assets): add square crab avatar for the ClawReview GitHub App 512x512 crab-only crop of the ClawBox logo (wordmark removed, padded so a circular avatar mask keeps the claws). This is the image to upload when creating the ClawReview GitHub App β a stable raw URL beats the earlier non-square 87x128 crab PNG. * fix(ci): apply CodeRabbit review β app-token if-guard + shared backend CodeRabbit's 4 actionable findings on the bots: 1+2. app-token step's `if: env.HAS_APP` (both workflows) referenced env the step sets on ITSELF β a step's if can't see its own step-level env, so the App token would NEVER mint even with the secrets set. Hoisted HAS_APP to job-level env (visible to the step if), and scoped the minted token to only the permissions each bot needs (pull-requests+issues for review, issues for triage) instead of the full installation grant. 3. parseModelJson + the two transports (CLI/SDK) were duplicated across pr-review.mjs and issue-triage.mjs. Extracted to scripts/lib/ ai-backend.mjs (callClaude); both bots import it, so the transport stays in sync. This is the 'first SDK-shape change' trigger the earlier reuse analysis set for extraction. 4. Static @anthropic-ai/sdk import breaking the OAuth path β already fixed (lazy import); the shared backend now owns the sole lazy import, so pr-review.mjs no longer imports the SDK at all. Validated via the OAuth CLI transport with node_modules removed: both bots produce their mascot output through the shared backend. * fix(ci): address CodeRabbit re-review β tolerant SDK parse + read-only dry-run - ai-backend.mjs: viaSdk now uses parseModelJson (tolerant of fenced/wrapped JSON) instead of a bare JSON.parse, matching the CLI path. - issue-triage.mjs: DRY_RUN now gates the whole label block (ensure() + gh issue edit), not just the edit β a dry run is fully read-only.
* chore(ci): sync ClawReview + triage bots to beta pull_request_target and issues-triggered workflows run from the PR's/issue's BASE branch, so the bots must exist on beta too β otherwise beta-targeting PRs (most of our volume) never trigger ClawReview. Brings the exact CI files from main (#248): the new pr-review bot, plus the OAuth-transport + sync updates to the issue-triage bot. CI-only files, identical to main. * fix(ci): lazy-load the Anthropic SDK so the OAuth path needs no SDK The OAuth transport installs only the Claude Code CLI, not @anthropic-ai/sdk, but both scripts had a static top-level 'import Anthropic from @anthropic-ai/sdk' β evaluated at module load regardless of transport β so the review job crashed with ERR_MODULE_NOT_FOUND before running (passed my local test only because the SDK was left installed there). Moved the import into a dynamic import() inside reviewViaSdk/classifyViaSdk, reached only on the API-key fallback. Verified by running the OAuth path with node_modules removed. * feat(ci): reshape ClawReview into an informative mascot (not a reviewer) Per direction: ClawReview should be a knowledgeable, friendly crab mascot that greets and orients on issues/PRs β NOT a code reviewer racing CodeRabbit. PR bot (pr-review.mjs): - Dropped severity findings (P1/P2/P3) and pass/fail verdicts β that was the CodeRabbit-racing part. Schema is now summary + kind + touches + neutral 'highlights' (helpful heads-ups, never bug reports) + duplicate hint. - System prompt recast: 'you are the mascot, not a reviewer; CodeRabbit does the line-by-line; produce orientation, never verdicts'. Empty highlights is normal and encouraged. - Comment is now: greeting -> plain-language summary -> 'At a glance' (kind/touches/base/surface + deterministic policy heads-ups) -> optional 'Good to know' -> sign-off that explicitly defers to CodeRabbit. Issue bot (issue-triage.mjs): - Rebranded the triage comment as the same crab mascot (one character across issues + PRs): friendly greeting + summary + at-a-glance labels + next step. - Added DRY_RUN (prints the comment, skips label writes) for local testing. Deterministic policy checks stay β they're genuine ClawBox-specific value (beta-first, bun.lock, sensitive paths) CodeRabbit can't provide β but are now framed as friendly context, not a verdict. Validated end-to-end via the OAuth CLI transport on PR #227 and issue #232. * fix(ci): apply CodeRabbit review β app-token if-guard + shared backend CodeRabbit's 4 actionable findings on the bots: 1+2. app-token step's `if: env.HAS_APP` (both workflows) referenced env the step sets on ITSELF β a step's if can't see its own step-level env, so the App token would NEVER mint even with the secrets set. Hoisted HAS_APP to job-level env (visible to the step if), and scoped the minted token to only the permissions each bot needs (pull-requests+issues for review, issues for triage) instead of the full installation grant. 3. parseModelJson + the two transports (CLI/SDK) were duplicated across pr-review.mjs and issue-triage.mjs. Extracted to scripts/lib/ ai-backend.mjs (callClaude); both bots import it, so the transport stays in sync. This is the 'first SDK-shape change' trigger the earlier reuse analysis set for extraction. 4. Static @anthropic-ai/sdk import breaking the OAuth path β already fixed (lazy import); the shared backend now owns the sole lazy import, so pr-review.mjs no longer imports the SDK at all. Validated via the OAuth CLI transport with node_modules removed: both bots produce their mascot output through the shared backend. * fix(ci): address CodeRabbit re-review β tolerant SDK parse + read-only dry-run - ai-backend.mjs: viaSdk now uses parseModelJson (tolerant of fenced/wrapped JSON) instead of a bare JSON.parse, matching the CLI path. - issue-triage.mjs: DRY_RUN now gates the whole label block (ensure() + gh issue edit), not just the edit β a dry run is fully read-only.
Clawsweeper-inspired PR bot, owned by us, complementing CodeRabbit. On every non-draft, non-bot PR it posts (and thereafter updates β one comment, no spam) a structured advisory review:
<!-- clawreview-verdict:... -->marker for toolingpackage.jsonβbun.lockconsistency, conventional title (incl.release:), tests-expected (β₯10 src lines), size, and security-sensitive-path notices (βΉοΈ, notEmpirically tuned: replayed against the 40 most recently merged PRs β the naive checks would have warned on 55% of them (5 warnings on the routine release PR); the tuned set warns on ~35%, all genuine, release PRs clean.
Advisory by design: never closes PRs, never fails the pipeline (exit 0 on any error), humans decide β unlike clawsweeper's auto-close, which fits a firehose repo, not ours.
Security shape (
pull_request_targetdiscipline): the checkout is the base repo only β PR code is never checked out or executed; the diff is reviewed as data via the API (80 k char cap); PR title/body/diff are declared untrusted in the system prompt; SHA-pinned actions; job-scoped permissions; author-checked comment upsert.Activation
ANTHROPIC_API_KEYrepo secret with the issue-triage bot (@yalexx β same pending Settings item). Until set, it no-ops gracefully.pull_request_targetruns the workflow from the PR's base branch β a follow-up PR syncs this tobetaso beta-targeting PRs (most of our volume) trigger it too.Validated by dry-runs against real PRs: #217 (release promotion β 0 warnings), #238 (metaβmain β all pass), #227 (deviceβbeta β all pass), #243 (bot-skip fires).
Summary by CodeRabbit
New Features
Documentation