Files
werkregie/doc/prs/2026-10-12-PR#48-watch-pr.md
claude-code 12f5b86950
werkator build succeeded after 01:15
A coding agent watches its pull request until it must act (#48)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-12 16:57:01 +02:00

7.0 KiB

PR#48: A Coding Agent Watches Its Pull Request Until It Must Act

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR documentation is not maintained along with new PRs; treat it as a snapshot.

  • PR#44, whose conflict with main stayed unnoticed.
  • PR#43, which shows the human a conflict that an agent leaves.

Problem

On 2026-10-12, PR#44 waited for its merge while PR#41, PR#43 and PR#46 merged into main. Its coding agent watched only for the merge and for red statuses, not for Gitea's mergeable; the human found the conflict. Each agent builds such a watch loop of its own, and each one misses something else. The shared workflow also does not say that a conflict is the agent's to fix, nor that the version is the next free one.

Non-Goals

  • No watch after the session of the agent ends; "Du bist dran" shows the human a conflict that an agent leaves (PR#43).
  • No automatic rebase; the agent resolves a conflict itself.
  • No GitHub.

Specification

Feature: the watch of a pull request ends when its agent must act

Scenario#48.01: a merge ends the watch

… so that the agent deploys at once.

  • Given a watched pull request
  • When Gitea merges it
  • Then the watch ends with MERGED and the merge commit
Verified by

Scenario#48.02: a conflict with main ends the watch

… so that the agent rebases before the human has to notice.

  • Given a watched pull request
  • When another pull request merges and Gitea reports a conflict in two checks in a row
  • Then the watch ends with CONFLICT
Verified by

Scenario#48.03: a red build ends the watch

… so that the agent repairs the build.

  • Given a watched pull request
  • When the build of its head, e.g. by Werkator, fails
  • Then the watch ends with FAILED, the context and its description
Verified by

Scenario#48.04: a green build of a WIP pull request ends the watch

… so that the agent removes WIP: and starts the review.

  • Given a watched pull request with the title prefix WIP:
  • When all statuses of its head are successful
  • Then the watch ends with READY
Verified by

Scenario#48.05: a review that asks for work ends the watch

… so that the agent answers each review round.

  • Given a watched pull request in review by werkrevisor
  • When werkrevisor finishes with RED, with a verdict that needs a human, or with open hints
  • Then the watch ends with REVIEW and werkrevisor's description
Verified by

Scenario#48.06: a running review does not end the watch

… so that the agent is not woken for nothing.

  • Given a watched pull request whose build and review still run
  • When the watch checks it
  • Then the watch goes on
Verified by

Scenario#48.07: a draft behind main ends the watch

… so that a WIP: pull request is rebased before its review, too.

  • Given a watched pull request with the title prefix WIP:
  • When another pull request merges into main
  • Then the watch ends with BEHIND
Verified by

Solution

  • werkregie-dashboard watch-pr <URL of the pull request> checks the pull request every 30 s, --interval changes it. It prints one line and ends, by the first that applies: MERGED <commit>, CLOSED, BEHIND, CONFLICT, FAILED <context>: <description>, REVIEW <description>, READY.
  • The token comes from the entry of giteas in dashboard.yml whose url matches the pull request, as for the dashboard: token, tokenEnv or teaLogin; the watch only reads.
  • Gitea computes mergeable after a push or merge in the background; a single false can be stale, so a conflict counts after two checks in a row.
  • Gitea reports a draft, i.e. a pull request with WIP: , as never mergeable. For a draft, the watch compares the merge base with the head of main instead and ends with BEHIND when they differ. Its first run on PR#48 ended with a false CONFLICT for this reason.
  • The watch reads the review from werkrevisor's two statuses of the head, ai-review/gate and ai-review/assessment. It ends with REVIEW when the review asks the agent for work:
    • one of the two statuses is a failure or an error, e.g. after the verdict RED;
    • or the review is done, and ai-review/assessment is not a success, e.g. pending after YELLOW or a warning after ORANGE;
    • or ai-review/assessment is a success, but its description says that open hints hold the merge.
  • Its first run in a review missed ORANGE, since it looked for werkrevisor's words of YELLOW only.
  • A failure or an error of any other status, e.g. of Werkator's build, ends the watch with FAILED.
  • After 10 failed requests in a row, the watch ends with an error and exit code 3.
  • doc/agentic-workflow.md, the master copy:
    • the agent watches its pull request after each push until it must act;
    • a conflict with main is the agent's to fix at once;
    • the version is the next free one over main and the open pull requests, and is raised again after a rebase.
  • Version 0.29.0.

Open Questions

  • Where does the watch live: in a script beside git-push-as-claude-code.sh, or in a mode of werkregie-dashboard? In a mode of werkregie-dashboard, chosen by the human. It is written in Kotlin and tested like the rest of werkregie, and it reads the Gitea tokens from dashboard.yml.

Additional Changes

  • An entry of dashboard.yml that this version does not know is named on stderr and skipped, no longer fatal. On 2026-10-12, PR#47 added claude.summary to the configuration on think before its deployment; watch-pr failed on it, and so would the relay of version 0.26.0 at its next start, until PR#47 merged.