feat(features,service,desktop): a new automation starts from Code review, reviewed as Luke, at most five at once and fifty a day

Merged
DA
3d ago
+3765-16

Dean approved merging this without trying it first; the first live run on production is the end-to-end proof.

Summary

Part 2: the code review bot as an automation preset, the design Dean approved from the spike (#2753). Its settings are modelled on Cursor Bugbot's. It builds on the trigger settings from #2780 (merged) and the Settings rows #2837 moved the editor onto.

  • The preset (packages/features/src/automation-code-review.ts):

    • name "Code review";
    • trigger pull-request-updated with the generic GitHub trigger settings from #2780: From people and Luke's agents (not other bots), On opened, ready, and new pushes, drafts skipped, forks off;
    • guards 5 at once and 50 a day, preset values that aren't shown in the editor. A push at the limit is skipped, and the skip stands in the run history;
    • successful runs archived, so the review lives on GitHub;
    • the creator's model (no model is pinned).
  • The task (automation-code-review-prompt.ts) is the spike's final prompt:

    • at most N findings at P0/P1, each with the input or state that makes it fail, checked before posting;
    • it finds its own earlier threads by a hidden marker, resolving the ones a push fixed and never reposting the rest;
    • it reads the rules file and AGENTS.md from the base branch;
    • it posts a COMMENT review only, never approving or requesting changes.
  • Code review card. The task opens with a short settings block. When the block is there, the editor shows a titled Code review card of Settings rows, which reads and writes the block in place and leaves the rest of the task alone:

    • Comment when no issues are found, a SwitchRow (on);
    • Most findings, a SelectRow from 1 to 10 (5);
    • Rules file, a text row (REVIEW.md);
    • Fix what it finds, a SwitchRow (off), which pushes fixes to the pull request as Luke. Luke's agents' own pushes never trigger a run, so this can't loop.

    These are lines of the prompt, not an engine of their own. An automation whose task has no block shows no section.

  • Starting from it: a new automation's page has a Start from card whose Code review row offers Start from Code review. The press fills the draft in at once. It fills in the name, trigger and its settings, task, guards, and archiving; the repository and owner stay as chosen. Everything stays editable, and nothing reads the preset after save.

  • Run titles: a code review's run about a pull request names its agent Review #<n> <title> (automation-runs.ts's subjectTitle), building on #2941's #<n> <title>. The service knows a code review by the settings block its prompt opens with (readCodeReviewSettings), since nothing else is kept of the preset after save. This is #2781's one service change.

  • Docs: docs/proposals/code-review-bot.md, whose §1b maps each Bugbot setting to ours or a skip, with the reason. Also its research (Part E is the Bugbot inventory), results, harness, and show from the spike.

How to try it (from main, once deployed)

  1. ./scripts/run.sh on main, against production (the Luke GitHub App delivers its webhook to production alone). Turn on Settings › Experimental › Automations.
  2. Automations › New automation › Start from Code review. Choose a quiet repository the workspace's GitHub App reaches (not a busy one: with "From Luke's agents" on, it reviews every teammate's and agent's pull request there), then Create.
  3. In that repository, open a small pull request (not a draft) with a planted bug. Within a minute or two a run appears in the automation's Runs panel, named Review #<n> <title>, and its agent posts one COMMENT review as luke-agent[bot]. Push a fix: the next run resolves the fixed thread and posts nothing new.

Evidence

  • Platform-independent checks: pnpm check:affected passes.
  • New tests, each failing without the change:
    • automations-page.test.ts: a new automation started from Code review fills in at once (no wait before asserting), shows the Code review card, and is made on pull-request-updated with the preset's trigger settings, archiving its successful runs, guards 5/50, carrying the review task with the card's settings; an automation whose task has no settings block shows no Code review card.
    • automation-code-review.test.ts: the settings read back, change in place, and leave the rest of the task as it was; a line that no longer reads stands at its default.
    • automation-draft-model.test.ts: a draft carries its guards, so one that only took a preset's guards counts as changed, and a saved automation opens on its own.
  • The prompt was measured in the spike: 36 posted comments with 0 wrong; 4/4 planted bugs found; re-reviews resolved exactly the fixed threads (code-review-bot/results.md).
  • Bundle: renderer/renderer.js stays under its ceiling, with the baseline unchanged. The prompt rides in the Automations pages' own lazy chunk (#2805).
  • Test count: +6. The newest is in automation-runs.test.ts: a code review's run about a pull request names its agent Review #2905 View commands, failing without the change.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens unchanged.
  • Every behavior change has, in this PR, the test that fails without it. The prompt's words have no change-detector test.
  • Gateway envelope goldens unchanged.
  • No new as assertion, run outside the edges, raw async primitive, or dropped Effect.
  • Test count delta listed (+6).
  • No hand-rolled file replaced.
  • No CLAUDE.md/AGENTS.md sentence names a changed part.
  • PRIVACY.md unchanged.
  • Package deps: @luke/features gains the ./automation-code-review subpath, which @luke/service reads (it already depends on @luke/features).
  • Bundle-budget baseline unchanged.

Notes

  • Mac: this is a UI PR, and CI could not verify the Mac UI. ./scripts/verify.sh was not run.
  • Limits: showing guards in the editor is trivial (the wire and service already take guards; it's one row), but it isn't added.
  • Supersedes the spike #2753, which is closed.

🤖 Generated with Claude Code