Skip to content

A resumed run takes its pull request from the journal - #104

Merged
abedegno merged 1 commit into
mainfrom
fix/pr-from-journal
Sep 20, 2026
Merged

abedegno merged 1 commit into
mainfrom
fix/pr-from-journal

Conversation

@abedegno

@abedegno abedegno commented Sep 20, 2026 •

Copy link
Copy Markdown
Owner

What and why

The first wave on the closed loop found this, and it cannot resolve itself.

A run implemented before the closed loop has CI observations with no pr and no pr_state. back.latest_pr_state therefore reads None, which the ending rule deliberately treats as open — silence must not end a run — so record_run_outcome is refused. Meanwhile the derivation cannot rediscover the pull request by branch code or issue linkage, because the branch is long gone, so it settles on no pull request, records no observation, and returns timeout. Nothing in that cycle can ever write a pr_state. The run can never end, and every wave re-derives it.

Observed live at 14:14 UTC on 9a5978a: record_run_outcome {"outcome":"timeout"} -- refused: a run with an open pull request cannot end for muesli runs i726-… and i728-…, both at merge_requested, both with latest_pr_state: None. Their journals name the pull requests they asked to merge — #735 (merged 2026-08-30) and #730 — so the information was there all along.

The fix takes it from there. back.latest_pr prefers the newest observation's pr and falls back to the newest request_merge payload's: the journal names the pull request a run asked to merge, whatever discovery can still see. back-state reports that number, so a resumed run derives against a pull request it can actually observe, sees it merged, and ends.

Effect on the merge gate

The gate is untouched: no change to what evidence a merge needs, to _merge_gate, merge_ready_pr, or the kernel's authorisation.

One behavioural consequence is worth naming rather than hiding. A run stranded at merge_requested can now find its own pull request again, so if that pull request is still open the loop will finish the merge the run had already authorised. That is the recovery the closed loop exists for — a pass that died between request_merge and the merge itself — and it still requires the kernel's accept bound to the exact head being merged. The two runs that prompted this are both already merged, so they will simply end.

Testing

  • bash batch/run-queue.sh --self-test passes on Linux
  • New behaviour I depend on has a self-test case
  • Where there is a guard, I showed it going red as well as green

Python suite 1987 passed, 3 skipped (up 4, the new tests); --self-test rc 0 on macOS. No bash changed here, only the kernel reader and the CLI that feeds it; CI ran the self-test on Linux for this branch and it passed (6m19s), alongside the Python suite.

Four tests: the observation's pr wins when it has one; a legacy run with an observation carrying no pr takes the number from its merge request; a journal naming no pull request anywhere reports empty; and back-state prints the fallback. The second fails without the fix — it is the live case above, reduced.

Anything a reviewer should look at twice

  • Whether the merge request is the right source. A run can request a merge more than once; the newest wins, which matches "the pull request this run currently owns". It is not the same question as orphan adoption in spec §5, which is about a pull request with no run at all — this is a run that still knows its own.
  • The fallback deliberately does not invent a state. It supplies a number, not a pr_state; the loop still has to observe the pull request before the kernel will let the run end.

@abedegno
abedegno merged commit 5843a03 into main Sep 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant