Skip to content

docs(source-control): merge-forward for stale PR branches + statusCheckRollup running-check pitfall - #2513

Merged
kyle-sexton merged 2 commits into
mainfrom
cursor/pr-lifecycle-merge-forward-63e1
Aug 12, 2026
Merged

docs(source-control): merge-forward for stale PR branches + statusCheckRollup running-check pitfall#2513
kyle-sexton merged 2 commits into
mainfrom
cursor/pr-lifecycle-merge-forward-63e1

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Lands the two PR-lifecycle facts #1436 recorded from driving #1393/#1316/#1318/#1322 to merge, in the document that was prescribing the expensive path:

Version 0.53.110.53.14 (patch; 0.53.12/0.53.13 are claimed by in-flight PRs #2450/#2453/#2483/#2510 and #2469 — skipping past them per the #1746 collision pattern).

Test plan

  • npx markdownlint-cli2@0.23.2 on both edited markdown files — 0 issues.
  • Docs-only change to skill reference text; no scripts or hooks touched. The jq forms added are the ones from the issue, verified against gh pr view --json statusCheckRollup semantics.

Related

Fixes #1436

@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 35s —— View job


Security review — skipped (skip gate)

  • Gather context (PR diff, files changed)
  • Invoke /review:security-review per custom instructions
  • Post findings

Per /review:security-review's skip gate, this PR has no security-relevant surface: all three changed files are documentation/metadata —

  • plugins/source-control/.claude-plugin/plugin.json — version bump only (0.53.110.53.14)
  • plugins/source-control/CHANGELOG.md — changelog entries
  • plugins/source-control/skills/pull-request/reference/monitor.md — prose edits to skill reference guidance (merge-forward vs. rebase recommendation, statusCheckRollup jq selector documentation)

No code, scripts, hooks, or GitHub Actions workflows are touched, and no injection, authorization, credential-handling, or supply-chain surface is introduced. No security findings to report.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Last security-reviewed head: 0dc3aaa0b19d93e8c0ecaaa603bb3acbad0df2b4. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

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

Copy link
Copy Markdown

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: 05b05bcc6c

ℹ️ 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 thread plugins/source-control/skills/pull-request/reference/monitor.md
Comment thread plugins/source-control/skills/pull-request/reference/monitor.md
…s; statusCheckRollup running-check pitfall

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
@kyle-sexton
kyle-sexton force-pushed the cursor/pr-lifecycle-merge-forward-63e1 branch from 05b05bc to ac3231b Compare August 12, 2026 19:53
@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 32s —— View job


Security review — skipped (skip gate)

  • Gather context (PR diff, files changed)
  • Invoke /review:security-review per custom instructions
  • Post findings

Per /review:security-review's skip gate, this PR still has no security-relevant surface at HEAD ac3231b. The branch was merge-forwarded onto a newer main since the last review (hence the new head SHA), but git diff origin/main...HEAD shows the PR's actual content is unchanged from what was already reviewed — the same three doc/metadata files:

No code, scripts, hooks, or GitHub Actions workflows are touched, and no injection, authorization, credential-handling, or supply-chain surface is introduced.

Note: the two Codex review comments on this PR (incomplete statusCheckRollup node-type handling; fetching the base ref before merge-forwarding) are correctness/completeness concerns in documentation prose, not security findings — out of scope for this lane per its "security issues only" bar.

No security findings to report.
· Branch

@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 44s —— View job


Security review — skipped (skip gate)

  • Gather context (PR diff, files changed)
  • Invoke /review:security-review per custom instructions
  • Post findings

Per /review:security-review's skip gate (condition 3: "this head already has a successful security review that still applies"), this PR still has no security-relevant surface at HEAD 0dc3aaa.

git diff ac3231b..0dc3aaa on the three PR files is empty — the branch was merge-forwarded onto a newer main (pulling in unrelated commit f4f7d94) but the PR's own content is byte-identical to what was already reviewed at ac3231b:

No code, scripts, hooks, or GitHub Actions workflows are touched, and no injection, authorization, credential-handling, or supply-chain surface is introduced.

Note: the two open Codex review comments on this PR (incomplete statusCheckRollup node-type handling at monitor.md:190; fetching the base ref before merge-forwarding at monitor.md:293) remain correctness/completeness concerns in documentation prose, not security findings — out of scope for this lane's "security issues only" bar.

No security findings to report.
· Branch

@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 51s —— View job


Code review

  • Gather context (PR diff, files changed, CLAUDE.md / REVIEW.md)
  • Invoke /review:code-review criteria against the diff
  • Post findings

This is a docs-only change (skill reference prose + version bump + changelog) to plugins/source-control/skills/pull-request/reference/monitor.md. Since this guidance is followed literally by an agent driving the same pull-request skill, I treated inaccuracies in it as correctness bugs, not style nits, and verified each against the actual repo state rather than trusting the PR description's claims.

Two findings posted inline (both confirm and add repo-specific detail to the existing Codex review comments on this PR):

  1. monitor.md:190 — the new statusCheckRollup jq selectors only handle CheckRun nodes. I checked babysit_checks.py and confirmed the repo already has the correct dual-node-type (CheckRun vs StatusContext) classifier with the full failure vocabulary (ACTION_REQUIRED, STALE, STARTUP_FAILURE in addition to FAILURE/TIMED_OUT/CANCELLED) — the new selectors here are a narrower, inconsistent second implementation that can misreport a finished legacy status as "still running" forever.
  2. monitor.md:293 — the new merge-forward default doesn't fetch before git merge <remote>/<default-branch>, so it can merge a stale local tracking ref. I checked create.md:84-93 in the same skill, which already does git fetch "$REMOTE" "$DEFAULT_BRANCH" immediately before merging/rebasing — worth mirroring here.

No other correctness issues found in the diff (version bump and changelog entries are consistent with the prose changes). No security-relevant surface, consistent with the earlier security-lane pass on this PR.
· Branch

@kyle-sexton
kyle-sexton merged commit c70d757 into main Aug 12, 2026
65 of 67 checks passed
@kyle-sexton
kyle-sexton deleted the cursor/pr-lifecycle-merge-forward-63e1 branch August 12, 2026 20:22
# failures only
--jq '[.statusCheckRollup[] | select(.conclusion=="FAILURE" or .conclusion=="TIMED_OUT" or .conclusion=="CANCELLED")]'
# still running
--jq '[.statusCheckRollup[] | select(.status!="COMPLETED")]'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The two new jq selectors only classify CheckRun nodes correctly; statusCheckRollup also contains StatusContext nodes (legacy commit statuses), which carry state instead of status/conclusion.

  • "still running" (select(.status!="COMPLETED")): a StatusContext has no status field, so this is always true for it — a long-finished legacy status (state: "SUCCESS") is reported as still running forever.
  • "failures only": omits ACTION_REQUIRED, STALE, and STARTUP_FAILURE, which plugins/source-control/skills/babysit-prs/scripts/babysit_checks.py:21-29 already classifies as failing states alongside FAILURE/TIMED_OUT/CANCELLED. Those conclusions read as neither failing nor running here and get silently dropped.

The repo already has the correct classification for this exact union type in babysit_checks.py's check_category() (plugins/source-control/skills/babysit-prs/scripts/babysit_checks.py:44-51) — worth mirroring its node-type/state handling here rather than introducing a second, narrower selector.

Fix this →

**Stale branch recovery** — if CI fails because the branch is out of date with the default branch (merge conflicts, "branch is not up to date" errors, or tests failing due to default-branch-only changes): integrate (merge or rebase per the project's convention and the branch's own history), resolve conflicts conservatively, force-push with lease, restart the monitor loop from 3.1. Distinct from code failures — no research gate for the integration itself, only for conflicts requiring intent judgment.
**Stale branch recovery** — if CI fails because the branch is out of date with the default branch (merge conflicts, "branch is not up to date" errors, or tests failing due to default-branch-only changes): integrate, resolve conflicts conservatively, push, restart the monitor loop from 3.1. Distinct from code failures — no research gate for the integration itself, only for conflicts requiring intent judgment.

**Merge-forward is the default integration; rebase is the exception.** `git merge <remote>/<default-branch>` *into* the PR branch resolves staleness and pushes **fast-forward** — no force-push, no history rewrite. A rebase rewrites the branch and demands `git push --force-with-lease`, which permission classifiers commonly deny in autonomous/auto-mode sessions; the observed failure shape is a lane concluding every rebase costs a fresh branch + fresh PR + closing the old one (re-opening every review thread from scratch), when the stale branch never needed a rebase at all. Under a squash-only default branch, the merge commits inside the PR branch collapse to one commit on merge and linear-history requirements stay satisfied — repeated merge-forwards as the default branch moves cost nothing. Rebase only when the project's convention requires a linear PR branch *and* force-push is actually available.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This new default-integration guidance runs git merge <remote>/<default-branch> without first fetching, so it merges whatever the local remote-tracking ref happened to be at the last fetch — which can be stale by the time "stale branch recovery" (§3.2) or the mergeable pre-check (§3.1 step 1) actually fires, since CI/mergeable status can lag the last local fetch by minutes to hours. That reproduces the exact staleness this section is meant to resolve: merging an old tip either leaves the PR still CONFLICTING/behind, or falsely reports "already up to date" when it isn't.

create.md:84-93 already gets this right in the same skill — git fetch "$REMOTE" "$DEFAULT_BRANCH" immediately before computing the merge-base / merging. Worth adding the same fetch step here (or an explicit pointer to that snippet) before the git merge <remote>/<default-branch> instruction.

Fix this →

@github-actions

Copy link
Copy Markdown

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

cursor Bot pushed a commit that referenced this pull request Aug 12, 2026
…ckRollup running-check pitfall (#2513)

## Summary

Lands the two PR-lifecycle facts #1436 recorded from driving
#1393/#1316/#1318/#1322 to merge, in the document that was prescribing
the expensive path:

- **Stale-branch recovery now defaults to merge-forward.**
`monitor.md`'s mergeable pre-check (§3.1 step 1) and stale-branch
recovery rule (§3.2) both prescribed "force-push with lease" — but
auto-mode permission classifiers commonly deny force-push, and the
recorded consequence was a fresh branch + fresh PR + closing the old one
per rebase (the #1315#1377#1393 churn, with every review thread
re-opened on the successor). Merging the default branch *into* the PR
branch resolves staleness and pushes **fast-forward** — no force-push —
and under a squash-only default branch the merge commits collapse to one
commit on merge, so linear-history requirements stay satisfied. Verified
in the issue's own record: #1393 landed that way and #1318 was
merge-forwarded five times without needing a new branch. Rebase stays
available as the exception for projects requiring a linear PR branch
where force-push is actually permitted.
- **`statusCheckRollup` reports a running check as `conclusion: ""`
(empty string), not `null`.** The complement-shaped filter (`conclusion
!= null and != "SUCCESS"`) therefore counts every in-progress check as a
failure — the exact misreport in the issue (two "failing" checks that
were simply still running). The multi-PR scan section (§3.0.6, the one
place this skill reads `statusCheckRollup`) now documents the pitfall
with value-positive jq selectors for "failed" and "still running".

Version `0.53.11` → `0.53.14` (patch; `0.53.12`/`0.53.13` are claimed by
in-flight PRs #2450/#2453/#2483/#2510 and #2469 — skipping past them per
the #1746 collision pattern).

## Test plan

- `npx markdownlint-cli2@0.23.2` on both edited markdown files — 0
issues.
- Docs-only change to skill reference text; no scripts or hooks touched.
The jq forms added are the ones from the issue, verified against `gh pr
view --json statusCheckRollup` semantics.

## Related

Fixes #1436

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
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.

PR lifecycle: merge-forward avoids the rebase/force-push PR churn, and statusCheckRollup reports running checks as conclusion ""

2 participants