Agent workflows#
pw_ghish: GitHub CLI-like interface for Gerrit code reviews and CI checks
Gerrit provides commit-based patchsets, fine-grained inline comment threading, and server-side draft states. However, AI coding agents often struggle with Gerrit’s custom command-line tooling and REST APIs, having been primarily trained on Git and GitHub CLI workflows.
pw_ghish maps standard GitHub CLI (gh pr) commands directly to Gerrit
and LUCI infrastructure. This provides a familiar CLI interface while preserving
Gerrit’s review semantics, supporting effective human-agent pair programming
workflows.
This document describes common user journeys for AI-assisted engineering in
Pigweed and Gerrit projects using pw_ghish.
CUJ 1: Private draft steering#
When guiding an AI agent through complex refactors or multi-file changes, typing long prompts in a chat window is inefficient. Developers often want to inspect the code diff visually in Gerrit and annotate exact lines that need changes—without publishing those notes to other human reviewers or the public change history.
The Workflow#
Agent pushes initial implementation: The agent writes the code and pushes the change:
$ ./gh pr create -t "pw_ring_buffer: Add peek method" --draft
Engineer leaves private draft comments in Gerrit: The engineer opens the Gerrit web UI, reviews the diff, and clicks lines to leave inline comments and suggestions. The engineer does not click Send; the comments remain stored on the Gerrit server as unpublished drafts.
Agent pulls down private drafts and addresses feedback: The engineer simply tells the agent: “Please address my draft comments.” The agent inspects the change with
pr view --comments(orpr status, which previews up to two unpublished[DRAFT]comments inline):$ ./gh pr view --comments
pw_ghishdisplays the draft comments clearly marked with file paths, line numbers,[PS<N>]patchset tags, and[DRAFT]indicators.Agent updates the code and updates or removes the steering drafts: The agent implements the requested fixes, runs local unit tests, uploads a new patchset, and either updates the draft in place with its status note or deletes the temporary steering draft:
$ ./gh pr push $ ./gh pr comment --path pw_ring_buffer/ring_buffer.cc --line 42 \ -m "Done: switched to pw::Result." --resolved --draft # Or delete the private steering draft once addressed: $ ./gh pr comment --path pw_ring_buffer/ring_buffer.cc --line 42 --delete-draft
Key benefits#
Visual steering: Engineers can use Gerrit’s side-by-side diff viewer to direct the agent to specific lines and code contexts.
Privacy: Work-in-progress review notes remain private between the engineer and the agent until published or deleted.
CUJ 2: Staged review responses#
When a reviewer leaves feedback on a change, an agent can address the comments and prepare fixes. However, allowing an agent to publish public replies directly risks inaccurate explanations or premature thread resolutions.
pw_ghish addresses this through staged draft replies and resolutions.
The Workflow#
Agent inspects unresolved reviewer threads: The engineer asks the agent: “Address the reviewer comments on my change.” The agent inspects all active threads:
$ ./gh pr view --comments
Agent modifies code and verifies locally: The agent updates the source files to address the reviewer’s feedback and runs tests:
$ bazelisk test //...
Agent stages replies and resolutions as drafts: For each addressed comment, the agent replies using
--draftand--resolved:$ ./gh pr comment --path pw_ring_buffer/ring_buffer.cc --line 84 \ -m "Updated to return pw::Result<ConstByteSpan> instead of raw pointer." \ --resolved --draft
The reply is recorded in Gerrit as an unpublished draft reply, and the thread is marked resolved in the draft state.
Agent uploads the new patchset: The agent pushes the updated code:
$ ./gh pr push
Engineer reviews patch-to-patch diff and sends: The engineer opens Gerrit to verify:
Compares the new patchset against the previous patchset in the Gerrit diff viewer.
Sees the agent’s drafted inline replies positioned right beside each change.
If satisfied, the engineer clicks Send in Gerrit (or runs
./gh pr review --publishfrom the terminal) to publish all staged draft replies. If adjustments are needed, the engineer or agent edits the draft replies in place before publishing.
Key benefits#
Human verification: Public comments are not published without human review, allowing engineers to verify explanations before sending.
Direct thread replies: The agent writes draft replies directly into Gerrit’s review threads rather than printing them in a chat window.
CUJ 3: CL handoff via URL or branch#
Handing off an existing change to an agent—such as a patch needing updates or a failing build—often requires multi-step Git fetch refspecs.
With pw_ghish, checking out a change requires only the change number or URL.
The Workflow#
Handoff prompt: The engineer gives the agent a shortlink or URL: “Can you pick up pwrev/472267, fix the compiler warnings, and get tryjobs green?”
Agent checks out the change: The agent runs
pr checkoutwith the shortlink:$ ./gh pr checkout pwrev/472267
pw_ghishfetches the change ref from Gerrit, checks out the commit, and configures tracking branch metadata.Agent inspects state: The agent runs
pr statusorpr checksto see live tryjob status andpr view --commentsto check for outstanding review feedback:$ ./gh pr status $ ./gh pr checks
Agent makes forward progress and pushes: After fixing the code, the agent uploads an updated patchset:
$ ./gh pr push
CUJ 4: Watching CI and repairing failures#
In Gerrit workflows, presubmit tryjobs often run across dozens of builders for 15 to 30 minutes. Rather than manually polling the Gerrit or Milo web UI and clicking through nested recipe steps to inspect failure logs, an agent can monitor tryjobs and retrieve step failure snippets from the terminal.
The Workflow#
Agent pushes change and watches checks: The agent uploads the patchset with Commit-Queue enabled and watches the run:
$ ./gh pr push --cq $ ./gh pr checks --watch --fail-fast
pw_ghishpolls Buildbucket at a configurable interval (default: 15s).Fail-fast exit and failure log retrieval: If any blocking builder fails,
--fail-fastexits immediately and prints the failing step summary and log snippet to stdout:$ ./gh pr checks --watch --fail-fast ... ✗ docs-builder 2m36s https://ci.chromium.org/b/8671020269272436273 ... FAILURE: docs-builder (Build 8671020269272436273) Failing Step: "ninja" Summary: Sphinx documentation build failed: undefined label 'module-pw_foo' --- Log Snippet (stdout) --- pw_foo/docs.rst:14: WARNING: undefined label: 'module-pw_foo'
Tip
You can also inspect failure reports with
./gh run view --log-failed, view step execution trees with./gh run view -j <builder>, or retry failed builders with./gh run rerun --failed.Repair and re-upload: The agent reads the error output, edits the source file, tests the fix locally, and uploads an updated patchset:
$ bazelisk test //pw_foo/... $ ./gh pr push --cq $ ./gh pr checks --watch --fail-fast
Enable auto-submit: Once checks pass, the agent or engineer enables automated submission:
$ ./gh pr merge --auto
Key benefits#
Reduced context switching: The agent polls presubmits and surfaces step failures without manual browser navigation.
Terminal log snippets: Step failure summaries and log excerpts are printed directly to stdout.
CUJ 5: Dependent change stacks#
Large changes are often structured as a stack of dependent commits. Gerrit
tracks each commit as an independent change using its Change-Id.
However, pushing branches with multiple commits can inadvertently create unintended changes if target branches are misconfigured.
The Workflow#
Safety Stack Guard: If an agent attempts to push a branch with multiple unpushed commits,
pw_ghishhalts immediately and requires--stack:$ ./gh pr create --stack
Branch Memory: When updating an existing change within a stack,
pw_ghishdiscovers the change’s recorded target branch from Gerrit (via itsChange-Id). The agent never accidentally uploads updates targetingmainwhen the change was created against a feature branch.Stack Traversal: Agents can checkout any change in the stack by change number or shortlink, apply rebased updates, and push individual patchsets cleanly:
$ ./gh pr checkout 472260 $ git rebase origin/main $ ./gh pr push
CUJ 6: Asynchronous auto-submit#
Rather than polling CI checks in a loop waiting for presubmits to complete, engineers and agents can enable automated submission once reviews are complete.
The Workflow#
Approve and enable auto-submit: Once code review is satisfied, the agent or engineer enables automated submission:
$ ./gh pr merge --auto
LUCI Commit-Queue takes over:
pw_ghishvotes the change’s auto-submit label (e.g.Pigweed-Auto-Submit+1). As soon as all required tryjob builders pass and approvals are registered, the LUCI CV bot automatically rebases the commit ontoorigin/mainand submits it.Immediate offramp on failure: If submit requirements cannot be met (for instance, missing a mandatory
Code-Review+2approval),pr mergeimmediately reports the missing labels and hints at the required voting flags rather than silently hanging.
CUJ 7: Parallel multi-agent issue-to-CL workflows#
When running multiple AI coding agents concurrently across different bugs or
features, sharing a single Git checkout causes index collisions, while creating
fresh git worktree directories triggers cold Bazel builds from scratch.
By combining Issues (gh issue) and Worktrees (gh wt), engineers can dispatch parallel agents in isolated, warm Bazel build slots.
The Workflow#
Allocate a warm worktree slot for a Buganizer issue: The engineer or agent spins up a dedicated project slot directly from a Buganizer issue ID:
$ ./gh issue develop 315378787 --worktree ✓ Project "b-315378787-fix-channel-framing" mounted in slot pw-01
This mounts physical slot
pw-01, creates symlink~/wrk/projects/b-315378787-fix-channel-framing, and registers the workspace in the Antigravity (Jetski) IDE sidebar.Agent reads issue context from the active branch: Inside the mounted project directory, the agent inspects the bug description and discussion history without needing the issue number repeated:
$ ./gh issue view --comments
Agent implements fix, uploads CL, and drives CI: The agent writes the fix, runs incremental Bazel tests using the slot’s warm output base, and uploads a Gerrit CL linked to the bug:
$ bazelisk test //pw_rpc/... $ ./gh pr create --cq $ ./gh pr checks --watch --fail-fast
Park the project while awaiting human review: Once tryjobs are green and the CL is waiting on reviewer approval, the slot can be freed for the next task while keeping the branch and CL tracked in
./gh wt list:$ ./gh wt park b-315378787-fix-channel-framing