Skip to content

ci: hourly sweeper re-fires dropped pull_request CI runs#110889

Merged
steipete merged 3 commits into
mainfrom
claude/pr-ci-sweeper
Jul 18, 2026
Merged

ci: hourly sweeper re-fires dropped pull_request CI runs#110889
steipete merged 3 commits into
mainfrom
claude/pr-ci-sweeper

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fresh PRs race GitHub's merge-ref computation: the pull_request-open CI run either never attaches to the head SHA or is created as startup_failure/BuildFailed/(Unknown event) — which gh run rerun refuses to retry. Repo history shows ~10–16 such runs daily across all authors; every one of the last four maintainer PRs (#110472, #110528, #110623, #110812) needed a manual close/reopen to get CI. PRs silently sit without CI until someone notices.

Why This Change Was Made

Diagnosed in #110812 (which documented the manual remedy in AGENTS.md). The workflow triggers in ci.yml are correct; the drop is GitHub-side, so the durable fix is automation of the proven remedy. An hourly pr-ci-sweeper workflow scans recently updated open PRs, finds heads whose pull_request-event CI runs are missing or all startup_failure, and re-fires the event by close/reopen using the Barnacle app token (required: GITHUB_TOKEN-authored events do not trigger workflows).

Sweeping is destructive automation, so the guards carry the design: a 10-minute quiet window (merge-ref settling), 24h lookback, skipping drafts, merge conflicts, pending mergeability, and auto-merge PRs (closing cancels auto-merge, which reopening does not restore — this protects the generated locale-refresh PRs); authoritative revalidation of state/head/CI attachment immediately before mutation; a per-PR budget of two sweeper closes (counted against sweeper app identities only) and a per-sweep cap of ten; and reopen-on-unknown close ownership so the silent failure (PR stranded closed) always loses to the visible one (spurious reopen). Manual workflow_dispatch supports dry_run for observability. Decision logic lives in scripts/github/pr-ci-sweeper.mjs per the Barnacle pattern, with the classify function pure and table-tested.

Two accepted tradeoffs are documented inline: a SHA shared by two PRs can mask one PR's dropped run behind the other's (a skip-only miss — matching run.pull_requests instead would misclassify fork PRs, where GitHub leaves that array empty), and app-auth failover can at worst double the per-PR close budget to four.

User Impact

Contributor/maintainer experience: dropped PR-open CI self-heals within the hour instead of requiring someone to notice and close/reopen manually. No product or runtime surface changes.

Evidence

  • Failure evidence: gh api on run 29634070586 shows path: BuildFailed, display_title: "(Unknown event)", empty referenced workflows; 100 most recent startup_failure runs span five days, all pull_request events.
  • node scripts/run-vitest.mjs test/scripts/pr-ci-sweeper.test.ts — 12 table cases pin the decision surface (refire on missing/startup-failure-only runs; skips for draft, lookback, quiet window, conflict, pending mergeability, auto-merge, attached/queued/failed runs, exhausted budget).
  • node scripts/check-script-declarations.mjs — 235 contracts match (new .d.mts included); oxlint clean; workflow YAML follows the pinned-action + app-token-with-fallback pattern from auto-response.yml.
  • Barnacle app bot login (openclaw-barnacle[bot]) verified against live close events; app-slug is also passed at runtime from the token step outputs.
  • Structured autoreview (gpt-5.6-sol, xhigh): six cycles; accepted and fixed TOCTOU on human closes, auto-merge cancellation, cross-bot budget pollution, stranded-close recovery, late-attaching CI, and run-page truncation; final two findings rejected with verified reasoning (documented inline and above).
  • Post-merge plan: one workflow_dispatch with dry_run: true to observe classification, then a live dispatch.

Fresh PRs race GitHub's merge-ref computation: the open-event CI run can
drop entirely or be created as an un-rerunnable startup_failure (~10-16
runs daily). The sweeper lists recently updated open PRs hourly, finds
heads whose only pull_request-event CI runs are startup failures (or
missing), and re-fires the event by close/reopen with the Barnacle app
token (GITHUB_TOKEN events would not trigger workflows).

Safety: 10-minute quiet window, 24h lookback, skips drafts, merge
conflicts, pending mergeability, and auto-merge PRs (close cancels
auto-merge); revalidates state, head, and CI attachment immediately
before mutating; per-PR budget of two sweeper closes and a per-sweep cap
of ten; reopen-on-unknown ownership so a stranded close (silent) always
loses to a spurious reopen (visible); manual dispatch supports dry_run.

Accepted tradeoffs are documented inline: shared-SHA PR topologies can
mask a dropped run (skip-only miss; run.pull_requests matching would
break fork PRs), and app-auth failover at worst doubles the close budget.
@steipete
steipete marked this pull request as ready for review July 18, 2026 18:43
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: M maintainer Maintainer-authored PR labels Jul 18, 2026
@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: ci: hourly sweeper re-fires dropped pull_request CI runs This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3c741e0cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
ref: ${{ github.sha }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict privileged dispatches to the trusted branch

When this workflow is manually dispatched from a non-default ref, github.sha resolves to that selected branch or tag, so the later dynamic import executes its scripts/github/pr-ci-sweeper.mjs after the GitHub App token has been created. A collaborator able to push a branch and dispatch workflows can therefore run unreviewed branch code with the Barnacle installation credentials, bypassing protected-main review. Restrict manual execution to the trusted default branch and load the sweeper implementation only from that trusted revision before exposing the App token.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. labels Jul 18, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13db4fc9ab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +181 to +185
const botCloseCount = events.filter(
(event) =>
event.event === "closed" &&
event.actor?.type === "Bot" &&
sweeperLogins.has(event.actor.login),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Attribute close budgets to the sweeper, not Barnacle

This counts every close by a login in sweeperLogins as a sweeper attempt, but .github/workflows/auto-response.yml:32-47 authenticates with the same Barnacle apps and scripts/github/barnacle-auto-response.mjs:865-870 closes PRs. If such a PR is later legitimately reopened and that reopened CI event is dropped, one prior Barnacle close reduces its retry budget and two make this sweeper skip it entirely as refire-budget-exhausted; attribute budget entries to this workflow rather than the shared app identity.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 18, 2026, 3:08 PM ET / 19:08 UTC.

Summary
Adds an hourly GitHub Actions sweeper that detects recently opened pull requests with missing or startup-failed CI and re-triggers CI by guarded close/reopen operations using an app token.

PR surface: Tests +241, Config +67, Other +273. Total +581 across 4 files.

Reproducibility: yes. by source: manually dispatching the workflow from a collaborator-controlled ref makes github.sha select that checkout, and the workflow imports its module after creating the app token.

Review metrics: 1 noteworthy metric.

  • Privileged execution modes: 1 scheduled workflow plus 1 manual-dispatch mode. The branch-selectable manual mode changes the trust boundary of an otherwise default-branch scheduled automation.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Constrain or remove workflow_dispatch before the app-token step can reach branch-selected code.
  • [P1] Add a redacted trusted-main dry-run dispatch transcript after the security repair.
  • If the PR body update does not trigger review, ask a maintainer to comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The PR describes unit coverage and intended post-merge dispatches, but it has no after-fix redacted workflow-dispatch output proving the safe production path; after resolving the trust boundary, provide a trusted-main dry-run transcript with private details redacted. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] A collaborator who can push a branch and manually dispatch this workflow can select that ref, causing the workflow to import branch-controlled code with a Barnacle app token capable of closing and reopening pull requests.
  • [P1] The proposed post-merge dry-run does not establish that the privileged mutation path is constrained to trusted code, and a dry run cannot safely compensate for the trust-boundary flaw.

Maintainer options:

  1. Constrain execution to trusted main (recommended)
    Before merge, remove branch-selected manual execution or route manual dry runs through a fixed trusted-default-branch implementation before any app token is minted.
  2. Pause manual dispatch support
    If a trusted dispatch broker is not ready, land neither the current manual-dispatch workflow nor any equivalent branch-ref execution path.

Next step before merge

  • [P1] A concrete security finding blocks merge, but maintainers must choose whether trusted manual dispatch is worth retaining or whether schedule-only operation is the intended policy.

Maintainer decision needed

  • Question: Should this automation retain a manual dry-run entry point only through a separately trusted default-branch dispatch path, or ship schedule-only until such a path exists?
  • Rationale: The required fix is not merely a test adjustment: maintainers must choose the acceptable operator workflow while preserving the protected-main boundary for app-token-backed automation.
  • Likely owner: steipete — Recent merged and proposed work connects this contributor to both the dropped-CI diagnosis and the automation design.
  • Options:
    • Ship schedule-only first (recommended): Remove workflow_dispatch and retain the hourly schedule, which runs the default-branch workflow and avoids branch-selected privileged execution.
    • Add a trusted dispatch broker: Keep dry-run support only if a separately trusted default-branch workflow receives parameters and executes a fixed trusted revision before creating the app token.

Security
Needs attention: The PR introduces a concrete privilege-boundary regression: app-token-backed automation dynamically imports code from a manually selected repository ref.

Review findings

  • [P1] Restrict app-token execution to trusted main — .github/workflows/pr-ci-sweeper.yml:36
Review details

Best possible solution:

Keep the scheduled repair loop on trusted default-branch code and move any manual dry-run capability behind a trusted-default-branch dispatcher or remove it until that boundary can be enforced before the app token is available.

Do we have a high-confidence way to reproduce the issue?

Yes, by source: manually dispatching the workflow from a collaborator-controlled ref makes github.sha select that checkout, and the workflow imports its module after creating the app token.

Is this the best way to solve the issue?

No. The hourly repair idea is bounded, but the proposed manual-dispatch design does not preserve the repository’s trusted-code boundary; a fixed trusted dispatcher or schedule-only implementation is safer.

Full review comments:

  • [P1] Restrict app-token execution to trusted main — .github/workflows/pr-ci-sweeper.yml:36
    workflow_dispatch can use a selected branch or tag, so this checkout imports scripts/github/pr-ci-sweeper.mjs from that ref after the Barnacle token is available. A collaborator with branch push and dispatch access can therefore execute unreviewed code with pull-request mutation credentials. Make the manual route execute a fixed trusted-default-branch revision before minting credentials, or remove manual dispatch and keep the schedule-only path.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.98

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5fdb0cd24e68.

Label changes

Label justifications:

  • P1: This can let unreviewed branch code operate a repository app token and alter pull-request state.
  • merge-risk: 🚨 security-boundary: The workflow dynamically imports branch-selected repository code after acquiring app credentials.
  • merge-risk: 🚨 automation: The app-backed close/reopen loop can affect CI attachment and pull-request lifecycle state across the repository.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR describes unit coverage and intended post-merge dispatches, but it has no after-fix redacted workflow-dispatch output proving the safe production path; after resolving the trust boundary, provide a trusted-main dry-run transcript with private details redacted. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Tests +241, Config +67, Other +273. Total +581 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 1 241 0 +241
Docs 0 0 0 0
Config 1 67 0 +67
Generated 0 0 0 0
Other 2 273 0 +273
Total 4 581 0 +581

Security concerns:

  • [high] Manual dispatch can run branch code with app credentials — .github/workflows/pr-ci-sweeper.yml:36
    The workflow checks out github.sha and later imports the sweeper module after the app-token steps. For workflow_dispatch, that SHA can be from the selected branch or tag rather than protected main.
    Confidence: 0.98

What I checked:

Likely related people:

What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete
steipete merged commit 53ad69c into main Jul 18, 2026
143 of 147 checks passed
@steipete
steipete deleted the claude/pr-ci-sweeper branch July 18, 2026 19:19
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 19, 2026
…0889)

* ci: add hourly PR CI sweeper for dropped pull_request runs

Fresh PRs race GitHub's merge-ref computation: the open-event CI run can
drop entirely or be created as an un-rerunnable startup_failure (~10-16
runs daily). The sweeper lists recently updated open PRs hourly, finds
heads whose only pull_request-event CI runs are startup failures (or
missing), and re-fires the event by close/reopen with the Barnacle app
token (GITHUB_TOKEN events would not trigger workflows).

Safety: 10-minute quiet window, 24h lookback, skips drafts, merge
conflicts, pending mergeability, and auto-merge PRs (close cancels
auto-merge); revalidates state, head, and CI attachment immediately
before mutating; per-PR budget of two sweeper closes and a per-sweep cap
of ten; reopen-on-unknown ownership so a stranded close (silent) always
loses to a spurious reopen (visible); manual dispatch supports dry_run.

Accepted tradeoffs are documented inline: shared-SHA PR topologies can
mask a dropped run (skip-only miss; run.pull_requests matching would
break fork PRs), and app-auth failover at worst doubles the close budget.

* test(ci): exercise pr-ci-sweeper runner with a faked client

* fix(test): lint-clean pr-ci-sweeper runner fakes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant