From: Mark Brown <broonie@kernel.org>
To: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
Cc: tools@kernel.org, Mark Brown <broonie@kernel.org>
Subject: [PATCH b4] review: Add a batch mode for agent reviews
Date: Wed, 11 Nov 2026 12:47:17 +0000 [thread overview]
Message-ID: <20261111-batch-agent-v1-1-7296d20c2a43@kernel.org> (raw)
Agent reviews can take quite some time to run which is not ideal for
interactive use. Add a command 'b4 review batch agent' which runs an agent
review for everything that is currently in reviewing state, allowing users
to ingest a batch of patches then review them all non-interactively.
Allow this to be limited to a specific agent in case the user is working
with multiple agents and wants to use them all.
There is a plan to offer batch operations on tagged commits in the TUI but
this feels like a case that's worth handling separately. As well as the
particularly long runtimes compared to other things that b4 does users
may also wish to do them in an isolated environment (or an environment
with better connectivity for that matter) so a mechanism for running
thigns non-interactively could be beneficial.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
docs/maintainer/review.rst | 39 +++++++++++++++++++++++++++++++++++++++
src/b4/command.py | 26 ++++++++++++++++++++++++++
src/b4/man/b4.1.rst | 9 +++++++++
src/b4/review/_review.py | 9 ++++++++-
4 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/docs/maintainer/review.rst b/docs/maintainer/review.rst
index 5a3e9d9..583e067 100644
--- a/docs/maintainer/review.rst
+++ b/docs/maintainer/review.rst
@@ -1832,6 +1832,45 @@ for your project. A sample prompt is included in
repository and adapt it to your project's coding standards and review
guidelines.
+Batch agent reviews
+~~~~~~~~~~~~~~~~~~~
+Run the configured review agent on all eligible series in the current
+repository with::
+
+ b4 review batch agent
+
+By default, the command selects review branches in the **Reviewing**
+state that do not already have an agent review attached to the series or
+any patch.
+
+New agent imports record their source explicitly. For older reviews,
+b4 treats notes or comments attributed to someone other than your configured
+user identity as agent reviews unless they carry mailing-list or Sashiko
+provenance, or are generated upgrade notes.
+
+To skip only series that already have a review from a particular agent,
+use its stored reviewer name::
+
+ b4 review batch agent --agent-name 'Review Agent'
+
+The name must exactly match the reviewer's display name from
+``identity.txt``, including case. Series reviewed by other agents remain
+eligible. The configured :term:`b4.review-agent-command` still runs;
+``--agent-name`` only filters existing reviews and leaves the agent's
+command and identity unchanged.
+
+To list eligible branches without running the agent or changing the
+repository, use::
+
+ b4 review batch agent --dry-run
+
+Agent failures are reported and the batch continues with the remaining
+series. The command exits with a nonzero status if any review fails.
+The agent is asked to write a summary even when it finds no issues;
+an invocation that produces no review data is reported as a failure and
+remains eligible for a later run. Review files left by an earlier run
+are imported before another agent is started.
+
.. _customising_theme:
Customising the colour theme
diff --git a/src/b4/command.py b/src/b4/command.py
index 18d9a9e..3a3c460 100644
--- a/src/b4/command.py
+++ b/src/b4/command.py
@@ -693,6 +693,32 @@ def setup_parser() -> argparse.ArgumentParser:
help='Output in JSON format',
)
+ # b4 review batch
+ sp_rev_batch = rev_subparsers.add_parser(
+ 'batch', help='Run review operations across multiple series'
+ )
+ batch_subparsers = sp_rev_batch.add_subparsers(
+ help='batch sub-command help', dest='batch_subcmd', required=True
+ )
+ sp_batch_agent = batch_subparsers.add_parser(
+ 'agent', help='Run the review agent on reviewing series without agent reviews'
+ )
+ sp_batch_agent.add_argument(
+ '--agent-name',
+ dest='agent_name',
+ default=None,
+ metavar='NAME',
+ help='Skip series only if an existing agent review has this exact '
+ 'reviewer name (case-sensitive; default: any agent)',
+ )
+ sp_batch_agent.add_argument(
+ '--dry-run',
+ dest='dryrun',
+ action='store_true',
+ default=False,
+ help='List eligible review branches without running the agent',
+ )
+
# b4 review cron
sp_rev_cron = rev_subparsers.add_parser(
'cron',
diff --git a/src/b4/man/b4.1.rst b/src/b4/man/b4.1.rst
index ded7d6e..c6b587e 100644
--- a/src/b4/man/b4.1.rst
+++ b/src/b4/man/b4.1.rst
@@ -332,6 +332,15 @@ For options and their descriptions, see ``b4 review --help`` and
list the series that would be cleaned up without changing the tracking
database.
+``b4 review batch agent [--agent-name NAME] [--dry-run]``
+ Run the configured review agent on every review branch in the current
+ repository whose state is reviewing and which has no agent review attached.
+ Reviews run sequentially and the original checkout is restored afterward.
+ Requires a clean working tree. Use ``--dry-run`` to list eligible branches.
+ With ``--agent-name NAME``, skip only series with an agent review whose stored
+ reviewer display name exactly matches NAME, including case. The configured
+ agent command still runs; this option only filters existing reviews.
+
``b4 review tui``
Launch the review TUI.
diff --git a/src/b4/review/_review.py b/src/b4/review/_review.py
index b69a7f0..bd74360 100644
--- a/src/b4/review/_review.py
+++ b/src/b4/review/_review.py
@@ -516,6 +516,10 @@ def main(cmdargs: argparse.Namespace) -> None:
cmd_show_info(cmdargs)
elif cmdargs.review_subcmd == 'cron':
cmd_cron(cmdargs)
+ elif cmdargs.review_subcmd == 'batch':
+ from b4.review import batch
+
+ batch.cmd_agent(cmdargs)
def get_review_branch_patch_ids(
@@ -1449,6 +1453,7 @@ def _integrate_agent_reviews(
series_reviews: Dict[str, Any] = series.setdefault('reviews', {})
entry: Dict[str, Any] = series_reviews.setdefault(reviewer_email, {})
entry['name'] = reviewer_name
+ entry['source'] = 'agent'
old_note = entry.get('note', '')
if old_note:
entry['note'] = old_note + '\n\n' + series_note
@@ -1524,6 +1529,7 @@ def _integrate_agent_reviews(
patch_reviews: Dict[str, Any] = patch.setdefault('reviews', {})
entry = patch_reviews.setdefault(reviewer_email, {})
entry['name'] = reviewer_name
+ entry['source'] = 'agent'
if comments:
existing_comments: List[Dict[str, Any]] = entry.setdefault('comments', [])
existing_comments.extend(comments)
@@ -1541,7 +1547,8 @@ def _integrate_agent_reviews(
# Save tracking — this amends the branch tip, changing its SHA so
# the directory is not re-consumed on the next run.
if branch:
- save_tracking_ref(topdir, branch, cover_text, tracking)
+ if not save_tracking_ref(topdir, branch, cover_text, tracking):
+ raise RuntimeError(f'Unable to save agent reviews on {branch}')
else:
save_tracking(topdir, cover_text, tracking)
logger.info(
---
base-commit: ce4c1158edb292caca0ce4a6087e5edecc1b0371
change-id: 20261111-batch-agent-a0fd59ffd824
Best regards,
--
Mark Brown <broonie@kernel.org>
reply other threads:[~2026-11-11 12:47 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261111-batch-agent-v1-1-7296d20c2a43@kernel.org \
--to=broonie@kernel.org \
--cc=konstantin@linuxfoundation.org \
--cc=tools@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.