Skip to content

ADR-0027: Ralph merge gate re-polls CI in place instead of rebuilding - #48

Merged
4lgn merged 1 commit into
masterfrom
claude/workflow-run-optimization-sktg1y
Aug 19, 2026
Merged

ADR-0027: Ralph merge gate re-polls CI in place instead of rebuilding#48
4lgn merged 1 commit into
masterfrom
claude/workflow-run-optimization-sktg1y

Conversation

@4lgn

@4lgn 4lgn commented Aug 19, 2026

Copy link
Copy Markdown
Member

Implements ADR-0027 to prevent slow CI from triggering expensive rebuild attempts in the Ralph workflow.

Summary

When the merge gate agent encounters a still-running CI (ci-timeout), the loop now re-polls the cheap gate in place up to POLICY.gateWaits times (default 6) before falling back to a fresh implementer attempt. This avoids wasting a full rebuild on CI that is merely slow, not broken.

Key Changes

  • Workflow gate re-poll loop: Modified drive() in both ralph.js and ralph.workflow.js to wrap the gate agent dispatch in a bounded loop that re-polls on ci-timeout without triggering a fresh build attempt.

  • New policy knob: Added gateWaits to POLICY (default 6, overridable per run) to bound the re-poll attempts. This is a workflow-only setting; skill-mode orchestration is unchanged.

  • Updated gate prompt: Clarified that the gate agent has one turn and cannot idle-wait. It now polls CI a few times and reports ci-timeout if still running—framed as a signal for cheap re-polling, not a failure. Re-polls include a waited counter so the prompt can indicate "it has very likely finished by now."

  • Test coverage: Added two new test suites that execute the workflow script against mock agents:

    • Verifies that a premature ci-timeout triggers in-place re-polls (gate:#n:ci-wait*) without spawning a fresh build attempt.
    • Confirms re-polls are bounded; a genuinely stuck CI eventually falls back to a fresh attempt and parks.
  • Documentation: Added ADR-0027 explaining the decision, alternatives considered, and consequences. Updated ADR-0022 reference to note it is amended by this ADR.

Implementation Details

The re-poll loop in drive() checks gate.status !== 'ci-timeout' || waited >= POLICY.gateWaits to exit early on any real verdict (merged, ci-failed, not-mergeable, failed) or when the re-poll budget is exhausted. Only then does the ticket fall back to the existing attempt/retry/park path. This ensures a slow-but-passing CI merges on the first attempt via cheap re-polls, while a stuck CI is still bounded and eventually parked rather than looping forever.

https://claude.ai/code/session_01EVZHX5ov5vFVjZcbHcya36


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

The workflow's merge gate is dispatched as a subagent, which structurally
cannot idle-wait on CI (a background sleep never resumes it). Given one turn
it polls CI a few times, sees `in_progress`, and returns `ci-timeout` — after
a minute or two, not the "~20 minutes" the prompt claimed. `drive()` then
treated `ci-timeout` like any failure and re-dispatched the *build* stage, so
a CI that was merely still running (the ~3-4 min norm) cost a full fresh
implementer (`build:#n:retry`) whose only real work was re-adopting the
already-open, already-green PR. ADR-0022 pre-registered exactly this under
"Revisit when: the gate-agent retry loop too expensive versus a repair-in-
place step."

Decouple the CI-wait re-poll from the build attempt:

- On `ci-timeout` the loop re-polls the same cheap gate agent in place (reads
  only until it can merge, effort low) up to POLICY.gateWaits times (default 6,
  per-run arg) before the ticket spends a fresh implementer attempt. Every real
  verdict — merged, ci-failed, not-mergeable — leaves the loop immediately; a
  CI that never lands still falls back to the unchanged attempt/park path once
  re-polls run out, so it can neither merge an unfinished run nor loop forever.
- Make the gate prompt honest: state the one-turn constraint, poll a handful of
  Monitor-spaced times, then report `ci-timeout` as a cheap re-poll signal
  (never a reason to merge on an unfinished run) instead of promising a 20-min
  wait it cannot perform.

Concurrent tickets in a round supply the wall-clock the re-polls ride on; at
width 1 they still cost only cheap gate agents, never an implementer.

Adds ADR-0027 (amends 0022), updates the registry, and notes the new
`gate:#n:ci-wait*` shape in the supervisor's "healthy shapes" list. Covered by
tests that execute the workflow script against mock agents and assert the
dispatch sequence: ci-timeout -> in-place re-poll with no build retry;
persistent timeout -> bounded re-polls -> fresh attempt -> park.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVZHX5ov5vFVjZcbHcya36
@4lgn
4lgn merged commit c1fe156 into master Aug 19, 2026
2 checks passed
@4lgn
4lgn deleted the claude/workflow-run-optimization-sktg1y branch August 19, 2026 12:22
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.

2 participants