Repository navigation
Open
Labels
bugSomething isn't workingSomething isn't workingfrom:redeployOrigin: reDeploy rolloutOrigin: reDeploy rolloutmodule:harnessOrchestrator machinery under .claudeOrchestrator machinery under .claude
Description
Summary
merge-ready.sh hardcodes gh pr merge --merge and discards gh's stderr. In any consumer repo whose branch ruleset restricts allowed merge methods, every bot merge is rejected by GitHub and the script logs only a bare {"action":"merge-failed"} — indistinguishable from a transient failure, forever, on every tick.
Incident (reDeploy, 2026-07-24 → 2026-07-30)
- reDeploy's "Main Branch Protection" ruleset allows squash only (created 2026-06-11, dormant while the repo was private on the free plan — rulesets don't enforce there).
- The repo went public on 2026-07-23, activating the ruleset.
- From the next owner approval onward, the bot's
--mergewas rejected: 435 consecutive silentmerge-failedticks. PR feat(core): first-class upgradeable contracts (UUPS/Transparent proxies) — #155 reDeploy#169 sat green + owner-approved for 5 days and was re-approved 3× to no effect; PRs loop-census.sh: advance_ready eligibility ignores needs-human label, only matches feat/issue-N-* branches #170/fix(needs-human): REST label ops + confirmed-episode guard — stop per-tick comment spam (issue #169) #171 then queued the same way. - Owner merges by hand kept working (RepositoryRole admin bypass), which masked the breakage.
- Diagnosis required reproducing the exact command outside the daemon because the script swallows the error (
>/dev/null 2>&1). - Interim fix applied repo-side: reDeploy's ruleset now also allows
merge. The script defect remains latent for every other consumer.
Proposed fixes
- Don't hardcode the merge method. Read it from the adapter (
gates.json→ e.g.merge.method) and/or fall back to what the repo actually permits (gh api repos/{repo}/rulesets→pull_request.parameters.allowed_merge_methods, and the repo'sallow_*_mergeflags). A squash-only repo should get--squashautomatically. - Surface the error. Capture
gh pr mergestderr and include it in themerge-failedJSON line ("error": "..."), so one journal read identifies the cause instead of requiring an out-of-band repro. - Distinguish remote-merge failure from local cleanup failure. With
--delete-branch, gh exits non-zero if the head branch is checked out in a.claude/worktrees/worktree even though the remote merge succeeded. The script then reportsmerge-failedon a merged PR and skipsclean_worktree, leaving exactly the debris that census can mistake for in-flight work. Check the PR's merged state (or split the merge and the branch deletion) before deciding what to report.
Notes
- reCode itself doesn't trip on this today only because its own ruleset has no
pull_requestrule — the defect is in the shipped script, so every consumer repo with a merge-method restriction inherits it. - Observed on the merge-ready.sh generation that runs all gh calls via bot-gh.sh (two-root derivation, scripts break when run from the plugin install cache (CLAUDE_PLUGIN_ROOT): root derived as ../.. conflates plugin root with consumer project root #63) as well as reDeploy's older vendored copy.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingfrom:redeployOrigin: reDeploy rolloutOrigin: reDeploy rolloutmodule:harnessOrchestrator machinery under .claudeOrchestrator machinery under .claude
Activity