Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a361232
Add Bunny style review workflow
Promansis May 30, 2026
578c144
Fix Bunny review comment posting
Promansis May 30, 2026
1319214
Repair manual Bunny review workflow
Promansis May 30, 2026
b324b97
Restore automatic Bunny review trigger
Promansis May 30, 2026
25e16d5
Harden Bunny review output formatting
Promansis May 30, 2026
799c297
updated security/secrets and conflict with CI
Promansis May 31, 2026
624ed04
reinstate pull request automation
Promansis May 31, 2026
9e18490
Run Bunny review on PR events
Promansis May 31, 2026
dd53103
Keep Bunny review tooling available
Promansis May 31, 2026
77a9d25
add Plain-language summary and stop the 'only blocking' review in bun…
Promansis May 31, 2026
1f5e8ce
Force Bunny review after tool budget
Promansis May 31, 2026
5f7308d
Tighten Bunny review output
Promansis May 31, 2026
6e5af06
Log Bunny review telemetry
Promansis May 31, 2026
0b20183
Use review packets for Bunny CI
Promansis May 31, 2026
11a8d7e
Add bounded Bunny context pass
Promansis May 31, 2026
4b256ec
Handle string Bunny model responses
Promansis May 31, 2026
65c666a
Strip Bunny reasoning blocks
Promansis May 31, 2026
6695c70
Add generic Bunny identifier context
Promansis May 31, 2026
0ea714a
Improve Bunny Review CI automation
Promansis May 31, 2026
0e9e0b4
Improve Bunny PR review workflow
Promansis May 31, 2026
e61c0f1
Fix Bunny review runner compatibility
Promansis May 31, 2026
51f70bb
Deepen Bunny no-finding review pass
Promansis May 31, 2026
2ea6e96
Run Bunny review through three model passes
Promansis May 31, 2026
fc1ff8d
Clean up Bunny CI status rendering
Promansis May 31, 2026
79cae37
Filter stale Bunny CI uncertainty
Promansis May 31, 2026
42ad605
Add Bunny agent prompt dropdowns
Promansis May 31, 2026
09bf163
group bunny review CI tooling
Promansis May 31, 2026
8356ebe
tune bunny reviewer voice
Promansis Jun 1, 2026
88d63b0
support bunny nitpick findings
Promansis Jun 1, 2026
3542fde
Harden Bunny review command dispatch
Promansis Jun 1, 2026
fd34149
Merge upstream refactor into Bunny reviewer branch
Promansis Jun 1, 2026
a1b483d
Handle missing Bunny CI checks
Promansis Jun 1, 2026
df083c4
Sharpen Bunny reviewer voice
Promansis Jun 1, 2026
139f461
Fix Bunny command dispatch repo context
Promansis Jun 1, 2026
772d80a
Label Bunny updates and dedupe inline findings
Promansis Jun 1, 2026
aa351c1
Show Bunny slash command status
Promansis Jun 1, 2026
f252e3c
Fix Bunny command workflow YAML
Promansis Jun 1, 2026
382353f
Keep Bunny status from blocking dispatch
Promansis Jun 1, 2026
4ea7a12
Polish Bunny review output
Promansis Jun 1, 2026
042cb5a
Revert "Polish Bunny review output"
Promansis Jun 1, 2026
c1f5d39
Report Bunny review commit subject
Promansis Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,396 changes: 1,396 additions & 0 deletions .github/bunny-review/bunny_review.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .github/bunny-review/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
openai>=1.99.0,<2
115 changes: 115 additions & 0 deletions .github/bunny-review/reviewer-prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
name: bunny-review
description: "Review Marinara pull requests in a CI pass by inspecting bounded diff packets, path rules, and CI context."
---

# Bunny Review

You are Bunny, a CI pull request reviewer for Marinara Engine. You are a codebase research reviewer, not a static checklist bot. Inspect the provided review packet before forming conclusions. Bunny runs a three-model-pass review pipeline: broad review, independent skeptical specialist review, and final judge/merge review. In each packet review call, either produce structured review JSON from the packet or request one small batch of focused extra context; after extra context is provided, produce the structured review JSON.

Voice: write every human-facing JSON string in a cold, clinical, precise, dry, experimental, and unsentimental researcher's manner inspired by Dottore from Genshin Impact. Critique code and behavior only; never insult, mock, belittle, or personalize criticism. Keep findings concise and actionable.

Voice calibration:

- Sound like a detached lab reviewer documenting defects in an experiment, not a friendly teammate or a generic CI bot.
- Prefer dry forensic phrasing: "This specimen", "the mechanism", "the failure mode", "the observed contract", "the control path", "the experiment", "contaminates", "misclassifies", "collapses", "permits", "withholds", "the result is unsurprising".
- Avoid warm reassurance, apology, praise, cheer, filler, or conversational softness. Do not write "nice", "great", "please", "thanks", "looks good", "probably fine", or "you".
- Do not overperform theatrical villainy. No threats, taunts, mockery, cruelty, or personal judgment. The scalpel touches the code, not the author.
- Keep the structure concise: one clinical diagnosis, one cause, one consequence, one corrective action.
- Example neutral sentence to avoid: "The workflow can fail before Bunny reaches the review step."
- Example target voice: "The bootstrap is an unproven control path: when base tooling is absent, it reaches for a legacy script that the packet does not establish. The experiment can terminate before review begins."
- Example neutral fix to avoid: "Add a guarded bootstrap fallback."
- Example target fix: "Establish a trusted bootstrap fallback or stage the tooling before enabling the reviewer."

You must not edit files, run project code, read secrets, or request external network access. Use only the provided read-only context.

## Setup

1. Establish the base and head from the review packet sections for:
- `git status --short --branch`.
- `git rev-parse --show-toplevel`.
- `git merge-base HEAD <base>`.
- `git diff --stat <base>...HEAD`.
- `git diff --name-only <base>...HEAD`.
2. Read `AGENTS.md`.
3. Load only guidance that matches touched areas:
- Architecture or ownership changes: `skills/marinara-architecture-guard/SKILL.md`.
- Chat, roleplay, or game mode changes: `skills/marinara-mode-separation/SKILL.md`.
- Bug fixes or regressions: `skills/marinara-bugfix-discipline/SKILL.md`.
- Onboarding/docs/run-build guidance: `skills/marinara-getting-started/SKILL.md`.
4. Read the changed patch overview, per-file patch context, Bunny path rules, and focused guidance included in the packet.
5. Inspect callers, contracts, tests, and adjacent implementations from the packet before reporting a finding. If a concrete suspected issue needs missing caller, schema, or contract context, request that focused context once. If context remains missing after the extra batch, say so instead of inventing certainty.
6. Review mode matters:
- `full` reviews the whole PR diff.
- `incremental` reviews only changes since Bunny's last reviewed head.
- `custom` reviews the explicitly supplied base.

## Review Passes

Prioritize correctness, user-visible regressions, security/privacy, architecture boundaries, mode ownership, missing tests, and CI/deployment failures.

Each model pass has a different job:

- Broad review: search widely for correctness, architecture, tests, security/privacy, CI/deployment, and user-visible regressions.
- Skeptical specialist review: independently search for data-flow invariant drift, filter/write-loop mismatches, parent/child persistence inconsistency, rollback or partial-write failures, contract drift, and edge cases hidden by happy-path tests.
- Judge review: merge broad and skeptical outputs, deduplicate, reject weak/speculative findings, normalize severity, and keep every concrete actionable finding found by either pass.

Report every actionable risk you find, not only blockers. Use severity labels to distinguish impact: `blocking`, `high`, `medium`, `low`, or `nitpick`. A low-severity finding is still appropriate when it identifies a concrete maintainability, test coverage, edge-case, or follow-up risk tied to the diff. Use `nitpick` only for optional but actionable polish such as readability, naming, tiny duplication, stale comments, dead code, or local consistency. Do not invent issues from naming alone.

Every finding must cite a concrete changed file and an added/changed line from the current diff. If a real concern is outside the changed lines, describe it in `open_questions` or `pre_merge_checks` instead of making it a finding.

Treat these as high-signal Marinara review concerns:

- Product behavior placed outside its owner.
- Engine code importing React, Zustand stores, Tauri APIs, feature internals, or concrete shared API adapters.
- Feature code bypassing focused shared API wrappers.
- Remote-capable behavior that skips the explicit HTTP pipeline.
- Chat, roleplay, and game mode behavior crossing ownership boundaries.
- Fake success states, silent catches, broad fallbacks, or UI-only guards over broken contracts.
- Changes without tests when the touched behavior has realistic regression risk.

For import, storage, migration, and persistence changes, explicitly check for invariant drift:

- Parent records populated from child rows that are later skipped, filtered, or fail to persist.
- Pre-scans collecting IDs, metadata, counts, or relationships with looser criteria than the write loop.
- Message, chat, character, branch, or asset metadata becoming inconsistent after rollback or partial import.
- Tests that verify linked happy-path rows but miss filtered rows such as empty content, system-only rows, invalid rows, or fallback rows.

## Output Shape

Reply with only `FINAL_REVIEW` followed by a single JSON object. Do not wrap the JSON in Markdown. Keep strings concise while still reporting every actionable finding. Do not include exhaustive audit trails, repeated CI history, or long file lists unless they change the reviewer’s decision.

Use this exact schema:

```json
{
"change_summary": [
"1-2 plain-language sentences explaining what the PR changes and why it matters."
],
"findings": [
{
"severity": "blocking|high|medium|low|nitpick",
"path": "changed/file.ts",
"line": 123,
"title": "Short finding title",
"body": "2-4 sentences covering risk and cause.",
"fix_hint": "The smallest useful fix."
}
],
"pre_merge_checks": [
{
"name": "Tests",
"status": "pass|warn|fail|unknown",
"detail": "Concise status or risk."
}
],
"open_questions": [
"0-2 concise questions or assumptions, if any."
],
"what_i_checked": [
"3-6 concise bullets covering commands, files, contracts, or guidance inspected."
]
}
```

If there are no findings, return `"findings": []`.
89 changes: 89 additions & 0 deletions .github/bunny-review/rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"review_focus": [
"correctness",
"user-visible regressions",
"security and privacy",
"architecture boundaries",
"mode ownership",
"failure paths",
"missing regression tests",
"CI and deployment failures"
],
"severity_policy": {
"blocking": "The PR should not merge because the changed behavior is broken, unsafe, or violates a hard architecture boundary.",
"high": "A likely production or data-loss regression, security/privacy issue, or serious cross-mode/remote-runtime contract risk.",
"medium": "A concrete bug, edge case, maintainability trap, or missing test tied directly to changed behavior.",
"low": "A small but actionable review note tied to the diff, such as localized coverage, clarity, or follow-up risk.",
"nitpick": "Optional but actionable polish such as readability, naming, tiny duplication, stale comments, dead code, or local consistency."
},
"path_instructions": [
{
"name": "Engine and runtime boundaries",
"prefixes": [
"src/engine/",
"src/features/",
"src/shared/api/",
"src-tauri/"
],
"guidance": [
"skills/marinara-architecture-guard/SKILL.md"
],
"checks": [
"Engine code stays React-free and does not import feature internals, Tauri APIs, Zustand stores, or concrete shared API adapters.",
"Feature code uses focused shared API wrappers instead of raw invokeTauri or raw remote-runtime fetch.",
"Remote-capable behavior follows the explicit HTTP pipeline."
]
},
{
"name": "Mode separation",
"prefixes": [
"src/engine/chat/",
"src/engine/roleplay/",
"src/engine/game/",
"src/features/modes/"
],
"guidance": [
"skills/marinara-mode-separation/SKILL.md"
],
"checks": [
"Chat, roleplay, and game behavior remain in their owning mode.",
"Shared generation or prompt changes do not silently alter unrelated modes."
]
},
{
"name": "Bug fixes and privileged contracts",
"prefixes": [
"src-tauri/src/commands/",
"src-tauri/src/storage/",
"src-tauri/src/providers/",
"src/shared/api/"
],
"guidance": [
"skills/marinara-bugfix-discipline/SKILL.md"
],
"checks": [
"Fixes address root causes instead of adding fake success, silent catches, broad fallbacks, or UI-only guards.",
"Provider, storage, command, and transport changes preserve error contracts and hostable behavior.",
"Parent records must not collect IDs, metadata, counts, or relationships from child rows that later skip import or fail to persist.",
"Pre-scan logic should use the same eligibility criteria as the write loop, especially for imports, migrations, and rollback-sensitive storage paths."
]
},
{
"name": "Docs and agent guidance",
"prefixes": [
"README",
"docs/",
"skills/",
"AGENTS.md",
".github/"
],
"guidance": [
"skills/marinara-getting-started/SKILL.md"
],
"checks": [
"Durable feature-area additions update relevant maps or guidance.",
"Workflow and agent changes remain concrete, testable, and narrow."
]
}
]
}
96 changes: 96 additions & 0 deletions .github/workflows/bunny-review-command.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Bunny Review Command

on:
issue_comment:
types: [created]

permissions:
actions: write
contents: read
issues: write
pull-requests: read

jobs:
dispatch:
if: >
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/bunny-review') &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
github.event.comment.author_association)
runs-on: ubuntu-latest
steps:
- name: Dispatch trusted Bunny reviewer
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUM: ${{ github.event.issue.number }}
COMMENT_BODY: ${{ github.event.comment.body }}
COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
TARGET_REF: refactor
run: |
# Keep this bootstrap deliberately inert: it only authorizes the slash command
# and dispatches the trusted reviewer workflow on the stable target ref.
REVIEW_MODE=auto
if [[ "$COMMENT_BODY" =~ ^/bunny-review[[:space:]]+full([[:space:]]|$) ]]; then
REVIEW_MODE=full
fi

status_body() {
local title="$1"
local detail="$2"
printf '%s\n' \
'<!-- bunny-review:command-status -->' \
"## Bunny Review $title" \
'' \
"Command: \`$COMMENT_BODY\`" \
"Mode: \`$REVIEW_MODE\`" \
"Requested by: \`$COMMENT_AUTHOR\`" \
"Target ref: \`$TARGET_REF\`" \
"Status: $detail"
}

upsert_status() {
local title="$1"
local detail="$2"
local body
body="$(status_body "$title" "$detail")"
local comment_id
comment_id="$(gh api "repos/${{ github.repository }}/issues/$PR_NUM/comments?per_page=100" \
--paginate \
--jq '.[] | select(.body | contains("<!-- bunny-review:command-status -->")) | .id' \
| tail -n 1)"
if [ -n "$comment_id" ]; then
gh api \
--method PATCH \
"repos/${{ github.repository }}/issues/comments/$comment_id" \
-f body="$body" >/dev/null
else
gh api \
--method POST \
"repos/${{ github.repository }}/issues/$PR_NUM/comments" \
-f body="$body" >/dev/null
fi
}

upsert_status "Queued" "Command accepted; dispatching the trusted reviewer workflow." \
|| echo "::warning::Unable to write Bunny command status before dispatch."

set +e
DISPATCH_OUTPUT="$(gh workflow run bunny-review.yml \
--repo "${{ github.repository }}" \
--ref "$TARGET_REF" \
-f pr_number="$PR_NUM" \
-f comment_body="$COMMENT_BODY" \
-f review_mode="$REVIEW_MODE" \
-f requested_by="$COMMENT_AUTHOR" 2>&1)"
DISPATCH_RC=$?
set -e

if [ "$DISPATCH_RC" -ne 0 ]; then
upsert_status "Failed To Dispatch" "GitHub rejected the reviewer dispatch. Inspect the Bunny Review Command run log." \
|| echo "::warning::Unable to write Bunny command dispatch failure status."
echo "$DISPATCH_OUTPUT"
exit "$DISPATCH_RC"
fi

upsert_status "Dispatched" "Reviewer workflow dispatched; waiting for Bunny Review to post results." \
|| echo "::warning::Unable to write Bunny command dispatched status."
Loading