Skip to content

pr-merge lane: dispatch proof artifacts expire while the post-merge floor still counts older merges #7479

Open

Description

@kyle-sexton

Refs: #7476

Problem

pr-merge.yml proves its full-run dispatch with the artifact pr-merge-dispatched-<run id> (90-day retention). babysit_postmerge.check re-judges every auto-merge since the floor (the enabling config commit or the newest human close of a demotion record) on each run. Once a lane dispatch's artifact is deleted, an older lane merge loses its dispatch proof, reads as unverified, and after the 6-hour deadline as a dispatch failure, which holds the lane off.

Options

  1. Stop re-judging merges once verified: record the verification durably (for example a comment by the identity on the merged PR) and read that instead of the artifact.
  2. Bound the check to merges newer than the artifact retention, with a reason for why older merges are settled.
  3. Raise the floor on a schedule (for example a periodic config commit), keeping the window under 90 days.

Recommended: option 1. It is the only one that stays correct without depending on retention.

Evidence

Review thread on #7476 (pr-merge.yml upload-artifact retention-days: 90; babysit_postmerge.py _Context.lane_dispatched).

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 14, 2026
  2. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Known
    Flags: none
    Blocked by: none

    Decision recorded.

    Question: The merge lane proves each dispatch with an artifact kept 90 days. The post-merge check re-judges every merge since a fixed floor, so lane merges older than 90 days start failing and hold the lane. Options: (a) record verification durably in an App-identity comment on the merged PR and stop re-judging; (b) check only merges newer than 90 days; (c) raise the floor on a schedule.

    Owner's answer: (a) The code already uses identity-authored pin comments with an edited-comment check, and a write collaborator cannot post as the App. Basis: .github/workflows/pr-merge.yml:484-486; babysit_postmerge.py:602-623, :1098-1123.

    [quote truncated; the full decision is at the link]

    #7479 (comment)

    The decision picks option (a), which settles the one open design question. The refinement's acceptance criteria cover the marker, its author and edit checks, failure handling and tests. This reads as a defect in the post-merge check. No duplicate found among open issues.

    Automated triage, applied by the lanes App.

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

    @kyle-sexton
    MemberAuthor

    Decision recorded.

    Question: The merge lane proves each dispatch with an artifact kept 90 days. The post-merge check re-judges every merge since a fixed floor, so lane merges older than 90 days start failing and hold the lane. Options: (a) record verification durably in an App-identity comment on the merged PR and stop re-judging; (b) check only merges newer than 90 days; (c) raise the floor on a schedule.

    Owner's answer: (a) The code already uses identity-authored pin comments with an edited-comment check, and a write collaborator cannot post as the App. Basis: .github/workflows/pr-merge.yml:484-486; babysit_postmerge.py:602-623, :1098-1123.

    The owner accepted this recommendation as item D29 of a 32-decision batch in an attended backlog-shaping session on 2026-10-18. The batch question: "Accept all 32 recommendations, including the four flagged above (D2 close the relearn, D26 cross-repo sync without per-repo confirm, D10 narrow hook, D23 delete guard only)?" The owner answered: "Accept all 32 (Recommended)".

    Posted by AI from the owner's answer in that session.

  7. added
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 19, 2026
  8. kyle-sexton commented on Oct 22, 2026

    @kyle-sexton
    MemberAuthor

    Still live after #9186 and #9208 (merged 2026-10-22): an expired lane record is now read as an empty listing, so the merge holds as unlisted-record instead of failing. #9208 then dispatches one recovery run; that run is recorded, covers the merge and clears it. So expiry now costs one full run per expired merge on every floor window, rather than a demotion. The fix here still applies: settle merges once a complete read judged them green.

  9. kyle-sexton commented on Oct 22, 2026

    @kyle-sexton
    MemberAuthor

    Correction to my comment above: for an old merge, any recent recorded lane run on main already contains it, so late is non-empty and the hold clears with no extra dispatch (babysit_postmerge.py _judge, after #9208). Expiry mostly costs re-reading old merges each sweep. The settle-once fix is still the clean answer.

  10. removed
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 31, 2026
  11. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 31, 2026
  12. melodic-automation-lanes commented on Oct 31, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: a criterion names .github/workflows/pr-merge.yml, which the issue lane cannot push (patch-protected-path); a builder session takes it; its title or stated work names a charge (retention), which needs an owner decision. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  13. melodic-automation-lanes commented on Oct 31, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: admission moved the issue to status: needs-decision; its comment says why.

  14. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    and removed
    status: needs-decisionAwaiting a human or maintainer judgment call.
    on Oct 31, 2026
  15. melodic-automation-lanes commented on Oct 31, 2026

    @melodic-automation-lanes
    Contributor

    Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.

    Intended outcome: The post-merge check records each lane merge judged verified from a complete read as an App-identity comment on the merged PR, then reads that record and skips re-judging that merge, so expired dispatch artifacts no longer matter for it.

    Acceptance criteria

    • babysit_postmerge.py defines a settled-merge marker comment, authored by the agent identity, that is posted on a lane merge's PR when check judges it verified from a complete (non-partial) read of runs and artifacts
    • check() reads the settled marker for each lane merge since the floor and, when an identity-authored marker for that merge commit SHA exists, counts the merge as verified without calling lane_dispatched or reading its artifact
    • A marker written by anyone other than the agent identity, or an edited marker, is ignored, using the same author and edited-comment checks the pin comments use
    • A merge judged unverified, pending or failed, or read from an incomplete or unlisted artifact listing, gets no marker and is re-judged on the next run
    • A failure to post the marker does not change the verdict and is reported as a warning, and a retry on the next run posts it
    • A test shows a lane merge with a settled marker and no dispatch artifact stays verified and does not hold as unlisted-record or fail as dispatch
    • A test shows a merge with a marker from a non-identity author is still judged by its artifact
    • A test shows an unsettled merge whose artifact has expired is still not marked verified from the marker path
    • The pr-merge.yml comments and the babysit_postmerge.py docstring and artifact comment at line 87 are updated to say settled merges no longer depend on artifact retention
    • The repository's existing babysit_postmerge tests and lint pass

    External state: none

    Related work

    Sources read

    • context.json: owner's Decision recorded (2026-10-18) picks option (a), an identity-authored comment on the merged PR, and settles the design
    • context.json: maintainer comments of 2026-10-22 say the settle-once fix still applies after #​9186 and #​9208, since expiry costs re-reading old merges each sweep
    • plugins/source-control/skills/babysit-prs/scripts/babysit_postmerge.py:87: comment says the dispatch proof is an artifact that _Context.lane_dispatched reads
    • plugins/source-control/skills/babysit-prs/scripts/babysit_postmerge.py:1828: lane_dispatched reads the pr-merge-dispatched-<id> artifact
    • plugins/source-control/skills/babysit-prs/scripts/babysit_postmerge.py:2565: check() re-judges every auto-merge since merged_since on each run, with no settled-merge record
    • plugins/source-control/skills/babysit-prs/scripts/babysit_postmerge.py:1929: the lane records file carries answers between runs but only for unexpired artifacts
    • https:/​/github.com/melodic-software/claude-code-plugins: .base/.github/workflows/pr-merge.yml:523 and :2649 set the dispatched artifact retention-days to 30

    Automated refinement by the lanes App. Intake triages the issue again with it.

  16. removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 31, 2026
  17. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 31, 2026
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

    priority: mediumReal value, no hard deadline; normal backlog flow.status: needs-decisionAwaiting a human or maintainer judgment call.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions