The watcher waits for CI on a branch push, so agent:done never means "CI agreed" #220

Closed
opened 2026-08-30 08:23:26 +00:00 by viberfox-agent · 0 comments
Collaborator

Found by the 3-day retrospective on #218, reading the lane's own comments for 2026-08-29 and 2026-08-30.

What happens

Ten of ten tickets the lane finished in the period reached agent:done with this comment:

🤖 Marked agent:done without a CI verdict on <sha> — no workflow reported on this commit. The branch is waiting for review; check the run yourself before landing it.

#175, #176, #186, #187, #192, #197, #199, #201, #203, #206. Not one of them got a real verdict. The timeout path is not an exception here — it is the only path.

Why it happens, and why it is not a flake

.forgejo/workflows/ci.yml deliberately has no push trigger on branches, and says so in its own header comment: a branch with a PR open would otherwise be compiled three times from one commit on a capacity-3 runner. The stated trade is "a branch with no PR gets no CI. Open the PR, which is where a verdict is actually read."

The watcher pushes the branch and then waits for CI on the branch head, with no pull request open. There is nothing for CI to have said, and there never will be. The wait can only end in a timeout.

tools/autopilot.ts has already been fixed for exactly this (8b528a8, "open the pull request first — a branch push gets no CI at all"), and its shipReady now opens the PR before checking, with a comment saying that this was "the whole reason this lane's verdicts were empty". The watcher did not get the same fix.

Why it matters more than a noisy comment

docs/notes/agent-verification.md is unambiguous:

Only the third may decide a label, land a branch, or end a ticket. agent:done therefore means "CI agreed", not "the session said so".

Today it means "CI did not answer", on every ticket. That note is a standing fact in the tree and it is currently false — and the note's own opening line is about checks "that had been passing for months without checking anything".

For an autopilot ticket the damage is contained, because shipReady and tools/deploy-main each re-check independently and the label is not trusted. For a driven or hand-labelled ticket nothing downstream re-checks: agent:done is the last word, and it currently carries no information. The comment tells a maintainer to "check the run yourself" — there is no run to check, which reads as a runner flake rather than as configuration.

The fix

The one the autopilot already took: open the pull request before waiting, then poll the run on refs/pull/N/head. A verdict then exists to be read, and agent:done means what the note says it means. The docs-only case still needs the paths-ignore exception (#219 covers the same rule for the deploy step) — a prose branch has no run by design and should be recorded as "no CI by design", which is a different sentence from "CI did not answer".

Where it lives, and why this is a report rather than a build ticket

issue-watcher/watcher.ts, per docs/workflow.md (the components table, ~line 845) — a separate repository, in the cartopolis-issue-watcher container. It is not under tools/ and not in this tree, so the unattended lane cannot build it. Deliberately not labelled autonomous.

If the fix cannot be made out-of-tree soon, the smaller in-tree half is worth doing anyway: correct docs/notes/agent-verification.md so it records what agent:done currently means, rather than what it is supposed to mean. A false standing fact is worse than a documented gap — that is the note's own argument, applied to itself.

Filed by the retrospective on #218.

Found by the 3-day retrospective on #218, reading the lane's own comments for 2026-08-29 and 2026-08-30. ## What happens **Ten of ten tickets** the lane finished in the period reached `agent:done` with this comment: > 🤖 Marked `agent:done` **without a CI verdict** on `<sha>` — no workflow reported on this commit. The branch is waiting for review; check the run yourself before landing it. #175, #176, #186, #187, #192, #197, #199, #201, #203, #206. Not one of them got a real verdict. The timeout path is not an exception here — it is the only path. ## Why it happens, and why it is not a flake `.forgejo/workflows/ci.yml` deliberately has **no `push` trigger on branches**, and says so in its own header comment: a branch with a PR open would otherwise be compiled three times from one commit on a capacity-3 runner. The stated trade is *"a branch with no PR gets no CI. Open the PR, which is where a verdict is actually read."* The watcher pushes the branch and then waits for CI **on the branch head**, with no pull request open. There is nothing for CI to have said, and there never will be. The wait can only end in a timeout. `tools/autopilot.ts` has already been fixed for exactly this (`8b528a8`, *"open the pull request first — a branch push gets no CI at all"*), and its `shipReady` now opens the PR **before** checking, with a comment saying that this was "the whole reason this lane's verdicts were empty". The watcher did not get the same fix. ## Why it matters more than a noisy comment `docs/notes/agent-verification.md` is unambiguous: > Only the third may decide a label, land a branch, or end a ticket. `agent:done` therefore means "CI agreed", not "the session said so". Today it means "CI did not answer", on every ticket. That note is a standing fact in the tree and it is currently false — and the note's own opening line is about checks "that had been passing for months without checking anything". For an autopilot ticket the damage is contained, because `shipReady` and `tools/deploy-main` each re-check independently and the label is not trusted. For a **`driven` or hand-labelled** ticket nothing downstream re-checks: `agent:done` is the last word, and it currently carries no information. The comment tells a maintainer to "check the run yourself" — there is no run to check, which reads as a runner flake rather than as configuration. ## The fix The one the autopilot already took: **open the pull request before waiting**, then poll the run on `refs/pull/N/head`. A verdict then exists to be read, and `agent:done` means what the note says it means. The docs-only case still needs the `paths-ignore` exception (#219 covers the same rule for the deploy step) — a prose branch has no run by design and should be recorded as *"no CI by design"*, which is a different sentence from *"CI did not answer"*. ## Where it lives, and why this is a report rather than a build ticket `issue-watcher/watcher.ts`, per `docs/workflow.md` (the components table, ~line 845) — a **separate repository**, in the `cartopolis-issue-watcher` container. It is not under `tools/` and not in this tree, so the unattended lane cannot build it. Deliberately not labelled `autonomous`. If the fix cannot be made out-of-tree soon, the smaller in-tree half is worth doing anyway: correct `docs/notes/agent-verification.md` so it records what `agent:done` currently means, rather than what it is supposed to mean. A false standing fact is worse than a documented gap — that is the note's own argument, applied to itself. <sub>Filed by the retrospective on #218.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jeroen/cartopolis#220
No description provided.