Agent team

Review rules

Every PR gets an agent review before a human merges it. The reviewer checks these fixed rules, not taste.

Who reviews

  • The reviewer is never the author, and by default runs on a different runtime from the author: Claude writes and Codex reviews, or the other way round.
  • Reviewers come from agents.reviewers in botgumi.config.ts (or the track's override). If primary shares the author's runtime, second reviews instead.
  • High-risk PRs get both reviewers: payments, auth, contract changes, data migrations (the high tier). Mid and low tier PRs get one.

What the reviewer checks

Each failed check is a finding. The default severity is given; a reviewer may raise a non-blocking finding to blocking with a reason, never the other way round.

# Check Default
1 Matches the OpenAPI contract and the ADRs. Any contract change edits docs/api/openapi.yaml in the same PR and is called out. blocking
2 Every screen or endpoint touched handles loading, empty, error (retryable or not) and offline. blocking
3 Every new or changed user-facing string exists in en and zh-Hans, in the localization layer. No CJK-only logic. blocking
4 No placeholder numbers in production code paths. Seed data is labelled as seed. blocking
5 Every changed behaviour has a test. blocking
6 PR sections filled in: What, Why, How tested (with pasted CI output), Data-binding / contract changes, Known gaps. blocking
7 App code imports provider interfaces only, never a vendor SDK. blocking
8 Docs updated for changed behaviour (ADR-0005): a PR that changes behaviour, a contract or a design updates its module's pages, lists any new page in docs/manifest.json, and commits the rebuilt docs/public/; pnpm docs:check passes. blocking
9 Naming, clarity, small simplifications. non-blocking

Dashboard track

On top of the checks above, every PR that touches dashboard/ (ADR-0003):

# Check Default
D1 Counts only. No email, user ID, device ID, position, trace or review text in the page, its tables, the collector's output or its logs. blocking
D2 No number typed into the page. Every number comes from a source or a named calculation over sources, and carries its provenance (source, query or calculation, as-of time, link when there is one). blocking
D3 A failing source is named on its own panel and the others still load. The collector catches each source on its own and names the ones that failed. blocking
D4 Every panel handles loading, empty, error, offline, not connected (the missing key and the step that sets it) and stale (a morning source older than 48 hours). These replace check 2 for the dashboard. blocking
D5 A goal drawn on the page comes from the "Quality bar" section of the PRD and cites its line. No goal without one. blocking
D6 Keys are read-only, listed in the secrets inventory, and never reach the page or the tables. The collector only reads. blocking
D7 Cloud spend is labelled as an estimate. non-blocking

Design track

On top of the checks above, every PR that touches design/, and every PR that adds or changes a screen in ios/ or android/ (ADR-0004):

# Check Default
G1 The PR's stage follows a passed gate: brand brief, design system, lo-fi, hi-fi, screenshot direction, in order. blocking
G2 Tokens are in design/system/tokens.source.json. A colour, size or font on a board or in screen code is a token, not a literal. blocking
G3 Every screen in design/lofi/screens.md lists loading, empty, error and offline; every hi-fi screen has a board for each listed state. blocking
G4 Every hi-fi screen has a data-binding map (bindings.md), and every value on its boards comes from an example API response, local state or the device. No made-up numbers. blocking
G5 No screen code in ios/ or android/ before the screen's row is approved with its gate issue. Screen code matches its approved boards and binding map; a difference is a design issue first. blocking
G6 Strings on the boards have keys and exist in en and zh-Hans; the ready board is also drawn in zh-Hans. blocking
G7 node design/check.mjs passes, output pasted. blocking

Posting

  • One review per round, through gh pr review: --request-changes while blocking findings are open, --comment otherwise.
  • Then the botgumi/review commit status on the head commit: success only with zero blocking findings.
  • Each finding is a line: **blocking** or **non-blocking**, the check number, file:line, the problem, the fix.

Rounds

  1. The author fixes every blocking finding and pushes. CI must pass again.
  2. The reviewer reviews again. That is round 2.
  3. After 2 rounds with blocking findings still open, the orchestrator escalates to the human with the open findings.

Merging

The author never merges and never approves its own work. The orchestrator may merge only under merge-policy.md, which requires botgumi/review = success. Everything else waits for a human.