Skip to content

fix(source-control): apply a config change on main to pr-merge's policy read for PRs opened before it #8834

Closed

Description

@kyle-sexton

Refs: #7576

Problem

pr-merge reads its merge config (the rung and the switches that decide whether a lane PR may merge unattended) at the pull request's base SHA. GitHub does not move that SHA when the base branch advances, so a config change on main, such as a lowered rung or a turned-off switch, may not apply to PRs opened before it until they are synced.

Current behavior

  • plugins/source-control/skills/babysit-prs/scripts/babysit_merge_policy.py:177-186 (origin/main): resolve() reads pull_request(repo, number).get("base").get("sha") and then read_config_at(repo, sha).
  • plugins/source-control/skills/babysit-prs/scripts/babysit_gh.py:839-844 records that the PR's cached baseRefOid lags once the base branch advances ("verified empirically": ahead_by=0 against the stale value while the live tip showed behind_by=11). Whether REST base.sha and GraphQL baseRefOid are the same cached value is not recorded.
  • merge.max-in-flight already avoids this: it is read again, uncached, at the default branch head (babysit_merge.py, around line 4107).

Desired behavior

  1. Probe: on a test PR, move main, then compare REST pulls/<n> base.sha and GraphQL baseRefOid with the live tip. Record the result in this issue.
  2. If base.sha lags: list every setting the gate reads at the base SHA and decide, per setting, whether a stricter value on main must apply at once. For each one that must, read it at the default branch head as max-in-flight does, or take the stricter of the two values. The reason it is read at the base (babysit_merge.py:3069: "so a pull request cannot drop its own declaration") must still hold.
  3. If base.sha does not lag: close this issue with the probe result.

Known calls

  • Origin: Lane Funding's sweep (X2, 2026-10-21) asked whether the base SHA refreshes. The answer in code comments and the policy read are ours.
  • This is merge-lane work, ranked below plan delivery (2026-10-20 realignment).

Size Small, Complexity Medium, Uncertainty Knowable.

Activity

  1. added
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 21, 2026
  2. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 21, 2026
  3. github-actions commented on Oct 21, 2026

    @github-actions
    Contributor

    Thanks for the report. Automated triage handed this issue to a maintainer.

    Proposed work class: work-class: scoped
    Basis: automated intake triage; a maintainer confirms or changes it.

    Automated triage. A maintainer reviews it.

  4. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 21, 2026
  5. kyle-sexton commented on Oct 21, 2026

    @kyle-sexton
    MemberAuthor

    Probe result (2026-10-21 12:3xZ): base.sha lags. Main was at bb226d8420. REST pulls/<n> base.sha and GraphQL baseRefOid agree with each other and both stay at the PR's starting commit: #8809 890fcd4eff, #8822 ad020d08b5, #8789 504be6ceb0.

    So resolve() reads PipelineConfig at a stale commit (babysit_merge_policy.py:177-186, fields at :415-470). Settings read there include rung, authority, merge.report-only, merge.require-verifier-verdict, denied-paths, max-changed-lines, the merge.diff-check switches (high-path-floor, floor-paths, floor-script-scopes) and merge.dependabot.*. merge.max-in-flight is already read at the default branch head (_run_max_in_flight). The kill switch is an Actions variable, so it is not affected.

    Effect: tightening any of those settings on main does not reach a lane PR opened before the change until that PR's branch is updated.

    Proposed fix for step 2: read the config at both the base SHA and the default branch head, and take the stricter value per setting. A PR still cannot drop its own declaration (babysit_merge.py:3069), and a tightening on main applies at once. Loosening takes effect only once a PR's base includes it, which is the safe direction.

  6. kyle-sexton commented on Oct 21, 2026

    @kyle-sexton
    MemberAuthor

    Decision recorded. Owner, 2026-10-21 ("Lets go w/ recommendations"): build this now, ahead of plan work. Fix: read the merge config at both the base SHA and the default branch head and take the stricter value per setting. Security & Cost passes it before merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions