Inspiration

GitLab's built-in Code Review approved a change on our merge request !7 with "I finished my review and found nothing to comment on." Two minutes later our judge found a CI job that no ticket had asked for. A reviewer that only reads code cannot tell whether the change is the one that was asked for. We wanted a review that checks the change against the ticket and against what the human actually said.

What it does

Marshal is one GitLab Duo custom flow with five seats:

  • the inspector hears every submission first and asks what can be deleted or merged;
  • the reviewer raises findings against the ticket, the law and the code;
  • the judge rules on every finding under a fixed law and answers converged, continue or escalate;
  • the notary checks the ticket and the ruling against the human's own words, kept verbatim in records/;
  • the fixer repairs what was sent back, commits, and hands the change back to the inspector.

Opening a merge request starts the court through a "merge request created" trigger. On !17 it went from the MR being opened (14:59:58 UTC) to the notary's seal in under six minutes, with no mention and no command; a person merged it at 15:06:40.

How we built it

  • GitLab Duo Agent Platform custom flow (v1 YAML), published to the AI Catalog, with a mention trigger and a merge-request-created flow trigger.
  • The law lives in law/*.md and is read from main at run time, so a reviewed branch cannot change its own rules.
  • tools/diarist.py copies the conversation behind each ticket into records/, which the notary reads.
  • The court reviewed its own changes. Eleven tickets are closed (#3–#6, #8–#14), and the merge requests it heard carry its seats' notes.

Challenges we ran into

  • 56 laps. On !10 the seats went round 56 times without posting anything, until the platform's 600-step limit stopped the session. A seat entered again in the same session keeps its conversation and, with unchanged inputs, answers without working. The fix (!11) feeds the fixer's output to the reviewer, judge and notary, and the notary's verdict to the judge, so a re-entered seat has new input to work on.
  • Not found is not wrong. The fixer weakened a true sentence in an ADR because nobody could find its proof; the proof was in issue #7. That became law: a claim whose support cannot be found is unverifiable, not wrong, and it goes to the human instead of the fixer.
  • A flow cannot start another flow on this platform, so the whole court had to live in one flow.

Accomplishments that we're proud of

The court heard its own changes: the law was changed through the same tickets and merge requests it reviews, and the rules shown in the video each came from a failure on this project.

What we learned

An AI reviewer needs a source of truth outside the code: the ticket and the human's words. And a rule should come from a failure you can point to.

What's next

Re-hearing in a fresh session after each fix, and more real runs of the inspector and the fixer's sweep tables.

Built With

  • claude-code
  • gitlab
  • gitlab-ci
  • gitlab-duo-agent-platform
  • graphql
  • markdown
  • python
  • yaml
Share this project:

Updates

Submission history