From 62ee57123d37b68fbdcca1f7eb3e667fa4d72beb Mon Sep 17 00:00:00 2001 From: damocles Date: Wed, 19 Aug 2026 01:59:22 +0200 Subject: [PATCH 1/4] hive-forge: document ci-rerun --pr's event-type gap on PR status --- docs/ci.md | 16 ++++++++++++++++ hive-forge/src/verbs/ci_rerun.rs | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/ci.md b/docs/ci.md index 6c6e4e2e..6db8cafc 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -45,6 +45,22 @@ blocks merge. `hive-forge ci-rerun --pr N` dispatches a `workflow_dispatch` retrigger without an empty commit. +**`ci-rerun --pr` verifies the code but does not reliably move the PR's own +status checks.** Measured directly (raw `GET /repos/.../actions/tasks` +JSON): a genuine PR-triggered run carries `event: pull_request` with the +`#` pseudo-ref as its `head_branch`; a `ci-rerun --pr`-dispatched run +carries `event: workflow_dispatch` with the real branch name instead. +Forgejo's PR commit-status tracking appears scoped to `pull_request`-event +runs specifically, so a dispatched run — even a genuinely successful one — +never writes to that status slot. Reproduced with three dispatches on one +PR over 20+ minutes, all genuinely green, the PR's own status unmoved +throughout. There is no known token-accessible way around this — the +actual "rerun" web-UI button reruns the *same* run under the *same* event +type, but is CSRF-gated (see `ci_rerun.rs`'s own doc comment for why the +dispatch API is used instead). **Always re-check `pr-status` after a +dispatch and believe what it says; only a new commit is guaranteed to move +a stuck context.** + ### Running checks locally Don't run `nix flake check` directly — it dispatches to the shared build farm and diff --git a/hive-forge/src/verbs/ci_rerun.rs b/hive-forge/src/verbs/ci_rerun.rs index db038425..00a822de 100644 --- a/hive-forge/src/verbs/ci_rerun.rs +++ b/hive-forge/src/verbs/ci_rerun.rs @@ -25,7 +25,9 @@ //! `artifact-get`) and dispatches the SAME workflow on the SAME ref the //! run used (the run record's `prettyref` + `workflow_id`). //! -//! Dispatch re-runs the whole workflow, so there is no single-job variant. +//! Dispatch re-runs the whole workflow (no single-job variant). ⚠️ `--pr` +//! verifies the code but doesn't reliably move the PR's own status +//! checks — see `docs/ci.md`'s "CI checks" for why; re-check `pr-status`. use anyhow::{Context as _, Result, bail}; use clap::Args as ClapArgs; From 3e0a847e55815a49ed7af036b6bf246be0ab8589 Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 24 Aug 2026 14:39:40 +0200 Subject: [PATCH 2/4] docs(ci): reword ci-rerun status guidance away from 'push a commit to unwedge' --- docs/ci.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 6db8cafc..06d36cb1 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -56,10 +56,19 @@ never writes to that status slot. Reproduced with three dispatches on one PR over 20+ minutes, all genuinely green, the PR's own status unmoved throughout. There is no known token-accessible way around this — the actual "rerun" web-UI button reruns the *same* run under the *same* event -type, but is CSRF-gated (see `ci_rerun.rs`'s own doc comment for why the -dispatch API is used instead). **Always re-check `pr-status` after a -dispatch and believe what it says; only a new commit is guaranteed to move -a stuck context.** +type, and that's the only thing that reliably moves the status, but it's +CSRF-gated (see `ci_rerun.rs`'s own doc comment for why an agent's token +uses the dispatch API instead). **Always re-check `pr-status` after a +dispatch and believe what it says. Don't push a commit just to unwedge a +stuck status — that's the empty-commit anti-pattern this verb exists to +avoid, and it doesn't even work reliably for the same reason `ci-rerun` +doesn't (a brand-new commit's own `pull_request` run is genuine, but +convincing yourself the diff needed a commit it didn't is the actual +problem).** If the code is verified green — read the dispatched run's own +log (`hive-forge ci-log --run --job 0`; the verdict is its last line, +`Job succeeded`/`Job failed`) — but the status is stuck, that's an +operator action, not an agent one: ask them to click "rerun" on the PR in +the forge web UI. ### Running checks locally From 8f53c223c1b2bda7a7024a4436833a3b51051ab4 Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 24 Aug 2026 14:44:53 +0200 Subject: [PATCH 3/4] docs(ci): drop the factually wrong 'a new commit doesn't reliably work either' clause --- docs/ci.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 06d36cb1..70dec89b 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -56,15 +56,12 @@ never writes to that status slot. Reproduced with three dispatches on one PR over 20+ minutes, all genuinely green, the PR's own status unmoved throughout. There is no known token-accessible way around this — the actual "rerun" web-UI button reruns the *same* run under the *same* event -type, and that's the only thing that reliably moves the status, but it's -CSRF-gated (see `ci_rerun.rs`'s own doc comment for why an agent's token -uses the dispatch API instead). **Always re-check `pr-status` after a +type and does move the status, but it's CSRF-gated (see `ci_rerun.rs`'s +own doc comment for why an agent's token uses the dispatch API instead). +**Always re-check `pr-status` after a dispatch and believe what it says. Don't push a commit just to unwedge a stuck status — that's the empty-commit anti-pattern this verb exists to -avoid, and it doesn't even work reliably for the same reason `ci-rerun` -doesn't (a brand-new commit's own `pull_request` run is genuine, but -convincing yourself the diff needed a commit it didn't is the actual -problem).** If the code is verified green — read the dispatched run's own +avoid.** If the code is verified green — read the dispatched run's own log (`hive-forge ci-log --run --job 0`; the verdict is its last line, `Job succeeded`/`Job failed`) — but the status is stuck, that's an operator action, not an agent one: ask them to click "rerun" on the PR in From 504123f2c43ceaa8e67f6f98d4d2e32e9e0a9b56 Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 24 Aug 2026 14:46:23 +0200 Subject: [PATCH 4/4] docs(ci): actually trim the ci-rerun status section instead of layering more clauses --- docs/ci.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 70dec89b..cddcf88b 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -54,18 +54,12 @@ Forgejo's PR commit-status tracking appears scoped to `pull_request`-event runs specifically, so a dispatched run — even a genuinely successful one — never writes to that status slot. Reproduced with three dispatches on one PR over 20+ minutes, all genuinely green, the PR's own status unmoved -throughout. There is no known token-accessible way around this — the -actual "rerun" web-UI button reruns the *same* run under the *same* event -type and does move the status, but it's CSRF-gated (see `ci_rerun.rs`'s -own doc comment for why an agent's token uses the dispatch API instead). -**Always re-check `pr-status` after a -dispatch and believe what it says. Don't push a commit just to unwedge a -stuck status — that's the empty-commit anti-pattern this verb exists to -avoid.** If the code is verified green — read the dispatched run's own -log (`hive-forge ci-log --run --job 0`; the verdict is its last line, -`Job succeeded`/`Job failed`) — but the status is stuck, that's an -operator action, not an agent one: ask them to click "rerun" on the PR in -the forge web UI. +throughout. **Always re-check `pr-status` after a dispatch and believe +what it says — don't push a commit just to unwedge it, that's the +empty-commit anti-pattern this verb exists to avoid.** If the code is +verified green (`hive-forge ci-log --run --job 0`, verdict is the +last line) but the status is stuck, ask the operator to click "rerun" in +the forge web UI — it's CSRF-gated, so only they can do it. ### Running checks locally