Skip to content

feat(ci): reshape ClawReview πŸ¦€ into an informative mascot (+ SDK fix)#252

Merged
KrasimirKralev merged 5 commits into
ID-Robots:mainfrom
KrasimirKralev:feat/clawreview-mascot
Jul 5, 2026
Merged

feat(ci): reshape ClawReview πŸ¦€ into an informative mascot (+ SDK fix)#252
KrasimirKralev merged 5 commits into
ID-Robots:mainfrom
KrasimirKralev:feat/clawreview-mascot

Conversation

@KrasimirKralev

@KrasimirKralev KrasimirKralev commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Reshapes ClawReview from an advisory reviewer into a knowledgeable, friendly mascot that greets and orients on every issue/PR β€” deliberately not racing CodeRabbit (which keeps doing the line-by-line).

Supersedes #251 β€” includes that SDK lazy-load hotfix as its first commit.

What changed

  • PR bot: dropped severity findings (P1/P2/P3) and pass/fail verdicts. New output is a plain-language summary + kind/touches + neutral highlights (helpful heads-ups, never bug reports) + duplicate hint. Comment reads: greeting β†’ summary β†’ At a glance (kind Β· touches Β· base Β· surface + deterministic policy heads-ups) β†’ optional Good to know β†’ a sign-off that explicitly defers to CodeRabbit.
  • Issue bot: same crab mascot voice (one character across issues + PRs) β€” greeting + summary + at-a-glance labels + suggested next step. Added DRY_RUN for local testing.
  • Kept: the deterministic ClawBox-specific checks (beta-first, bun.lock, sensitive paths, area labels, dupes) β€” genuine value CodeRabbit can't provide β€” now framed as friendly context, not verdicts.
  • SDK fix (from fix(ci): lazy-load Anthropic SDK so the bots' OAuth path needs no SDKΒ #251): @anthropic-ai/sdk is imported lazily so the OAuth-only install path doesn't crash.

Validated

End-to-end via the OAuth CLI transport (SDK removed, exactly like CI): PR #227 and issue #232 both produce clean, informative mascot comments.

Auth stays on CLAUDE_CODE_OAUTH_TOKEN (already set). The crab avatar needs the ClawReview GitHub App (org-admin task, emailed to @yalexx) β€” the token wiring is already in place and no-ops until the App exists.

Summary by CodeRabbit

  • New Features

    • Issue triage and pull request review comments now use a refreshed, more user-friendly format with clearer β€œat a glance” summaries and suggested next steps.
  • Bug Fixes

    • Added safer dry-run behavior so labels and comments are not posted during test runs.
    • Improved handling for automated comments when the app token isn’t available.
  • Chores

    • Tightened automation permissions for issue and pull request workflows.

The OAuth transport (shipped in ID-Robots#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 ID-Robots#250.
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 ID-Robots#227 and issue ID-Robots#232.
@KrasimirKralev
KrasimirKralev requested a review from a team as a code owner July 5, 2026 10:03
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KrasimirKralev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 25e54024-6973-4236-873d-93f2632881d3

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between b63321c and 9fa5cf5.

πŸ“’ Files selected for processing (2)
  • scripts/issue-triage.mjs
  • scripts/lib/ai-backend.mjs
πŸ“ Walkthrough

Walkthrough

This PR introduces a shared Claude transport module (scripts/lib/ai-backend.mjs) used by both scripts/issue-triage.mjs and scripts/pr-review.mjs, replacing local CLI/SDK logic. It reworks generated comments into a "ClawReview" mascot format, adds DRY_RUN gating, and scopes GitHub App token permissions in the CI workflows.

Changes

ClawReview bot refactor

Layer / File(s) Summary
Shared Claude backend module
scripts/lib/ai-backend.mjs
Adds parseModelJson for extracting JSON from model text, viaClaudeCli and viaSdk transport implementations, and callClaude to dispatch between them based on CLAUDE_CODE_OAUTH_TOKEN.
Issue triage script migration
scripts/issue-triage.mjs
Replaces local Claude transport logic with callClaude, adds DRY_RUN gating for label edits and comment posting, and replaces the auto-triage comment with a new "ClawReview" greeting-based format.
PR review script migration
scripts/pr-review.mjs
Removes local Anthropic SDK usage in favor of callClaude, replaces the verdict/findings schema and prompt with a neutral kind/highlights/duplicate orientation schema, reworks comment rendering into an "At a glance" mascot format, and updates logging.
Workflow token scoping and gating
.github/workflows/issue-triage.yml, .github/workflows/pr-review.yml
Adds job-level HAS_APP env vars derived from secrets.CLAWREVIEW_APP_ID and scopes minted GitHub App tokens to permission-issues: write (issue-triage) and permission-pull-requests/permission-issues: write (pr-review).

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Script
  participant callClaude
  participant viaClaudeCli
  participant viaSdk
  Script->>callClaude: request(system, schema, userContent)
  alt CLAUDE_CODE_OAUTH_TOKEN set
    callClaude->>viaClaudeCli: run claude CLI
    viaClaudeCli-->>callClaude: parsed JSON result
  else fallback
    callClaude->>viaSdk: client.messages.create
    viaSdk-->>callClaude: parsed JSON text
  end
  callClaude-->>Script: validated JSON
Loading
sequenceDiagram
  participant PRReviewScript
  participant callClaude
  participant GitHubAPI
  PRReviewScript->>callClaude: system, schema, userContent
  callClaude-->>PRReviewScript: kind, touches, highlights, duplicate
  PRReviewScript->>PRReviewScript: build "At a glance" comment
  PRReviewScript->>GitHubAPI: post mascot comment
Loading

Possibly related PRs

  • ID-Robots/clawbox#221: Both PRs modify the same issue-triage workflow and script, reworking token gating and comment/label behavior.
  • ID-Robots/clawbox#238: Both PRs touch scripts/issue-triage.mjs and .github/workflows/issue-triage.yml, refactoring the same triage automation.
  • ID-Robots/clawbox#248: Both PRs modify scripts/pr-review.mjs for Claude structured-output review logic and related workflow setup.

Suggested reviewers: GeorgiK77

πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly reflects the main change: turning ClawReview into a mascot, with the SDK fix as a secondary note.
Description check βœ… Passed The description covers the summary and testing, but it omits several template sections like type of change and checklist.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests

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.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

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.
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.
@KrasimirKralev

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
βœ… Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/issue-triage.mjs (1)

62-72: πŸ—„οΈ Data Integrity & Integration | 🟠 Major | ⚑ Quick win

DRY_RUN still mutates the repo β€” ensure() creates labels before the gate.

The DRY_RUN guard on Line 72 only skips gh issue edit, but the ensure(...) calls on Lines 63, 64, and 69 run gh label create unconditionally. So a "dry" run still creates priority/area/category labels in the repo. This is inconsistent with pr-review.mjs, whose DRY_RUN returns before any mutation. Gate the label creation too.

πŸ› Proposed fix: gate label ensure + edit together
-  const prioColor = t.priority === "high" ? "b60205" : t.priority === "medium" ? "fbca04" : "0e8a16";
-  ensure(`priority: ${t.priority}`, prioColor, "Auto-triage priority");
-  ensure(`area: ${t.area}`, "c5def5", "Auto-triage area");
-  // `gh issue edit` applies all labels in one call and fails the whole command
-  // if ANY is missing β€” so the category label must exist too, even though
-  // bug/enhancement/etc. are GitHub defaults (a repo may have deleted them).
-  const catColor = { bug: "d73a4a", enhancement: "a2eeef", documentation: "0075ca", question: "d876e3", invalid: "e4e669" }[t.category] ?? "ededed";
-  ensure(t.category, catColor, "Auto-triage category");
-
-  const labels = [t.category, `priority: ${t.priority}`, `area: ${t.area}`];
-  if (!process.env.DRY_RUN) gh(["issue", "edit", String(number), "--repo", REPO, ...labels.flatMap((l) => ["--add-label", l])]);
+  const labels = [t.category, `priority: ${t.priority}`, `area: ${t.area}`];
+  if (!process.env.DRY_RUN) {
+    const prioColor = t.priority === "high" ? "b60205" : t.priority === "medium" ? "fbca04" : "0e8a16";
+    ensure(`priority: ${t.priority}`, prioColor, "Auto-triage priority");
+    ensure(`area: ${t.area}`, "c5def5", "Auto-triage area");
+    // `gh issue edit` fails the whole command if ANY label is missing β€” so the
+    // category label must exist too (a repo may have deleted the defaults).
+    const catColor = { bug: "d73a4a", enhancement: "a2eeef", documentation: "0075ca", question: "d876e3", invalid: "e4e669" }[t.category] ?? "ededed";
+    ensure(t.category, catColor, "Auto-triage category");
+    gh(["issue", "edit", String(number), "--repo", REPO, ...labels.flatMap((l) => ["--add-label", l])]);
+  }
πŸ€– Prompt for 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.

In `@scripts/issue-triage.mjs` around lines 62 - 72, The DRY_RUN guard in
issue-triage.mjs only protects the gh issue edit call, while the ensure() calls
for priority, area, and category still create labels and mutate the repo. Update
the triage flow around ensure(), prioColor, catColor, and the labels array so
all label creation and the issue edit happen only when DRY_RUN is not set,
matching the non-mutating behavior used in pr-review.mjs. Keep the dry-run path
fully read-only by gating the entire label setup and gh invocation together.
πŸ€– 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 `@scripts/lib/ai-backend.mjs`:
- Around line 39-53: The JSON parsing in viaSdk currently assumes the model
returns a bare object string, which can fail on fenced or prose-wrapped JSON.
Update viaSdk in ai-backend.mjs to reuse parseModelJson(text) instead of calling
JSON.parse directly, matching the CLI path behavior while keeping the existing
no-text error handling.

---

Outside diff comments:
In `@scripts/issue-triage.mjs`:
- Around line 62-72: The DRY_RUN guard in issue-triage.mjs only protects the gh
issue edit call, while the ensure() calls for priority, area, and category still
create labels and mutate the repo. Update the triage flow around ensure(),
prioColor, catColor, and the labels array so all label creation and the issue
edit happen only when DRY_RUN is not set, matching the non-mutating behavior
used in pr-review.mjs. Keep the dry-run path fully read-only by gating the
entire label setup and gh invocation together.
πŸͺ„ 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: c3dab3be-b672-44f3-a7f4-004c4a86e2d1

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between e4bd878 and b63321c.

β›” Files ignored due to path filters (1)
  • .github/assets/clawreview-avatar.png is excluded by !**/*.png
πŸ“’ Files selected for processing (5)
  • .github/workflows/issue-triage.yml
  • .github/workflows/pr-review.yml
  • scripts/issue-triage.mjs
  • scripts/lib/ai-backend.mjs
  • scripts/pr-review.mjs

Comment thread scripts/lib/ai-backend.mjs Outdated
…y 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.
@KrasimirKralev
KrasimirKralev merged commit 111446c into ID-Robots:main Jul 5, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant