Skip to content

fix(source-control): write the Siblings line when an issue has merged Refs pull requests - #13078

Merged
kyle-sexton merged 1 commit into
mainfrom
work-resolve-issue/issue-13068-41767948125-1
Nov 4, 2026
Merged

kyle-sexton merged 1 commit into
mainfrom
work-resolve-issue/issue-13068-41767948125-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Closes #13068

Summary

Opened by the work-resolve-issue lane. The run's own summary:

/source-control:pull-request create now writes a first-column Siblings: #<a>, #<b> line directly below the closing line when merged pull requests in the repository carry a Refs: #N line for an issue this PR closes and close no issue. With none, it writes no line. A new script, scripts/siblings-line.sh, does the lookup: one gh pr list --state merged search per closed issue, then a jq filter on the Refs: line and on empty closingIssuesReferences. It prints one line across all closed issues, keeping the 10 newest, because pr-verify's siblingNumbers credits nothing from a body that names more than 10. Design choice: the lookup is a tested script rather than inline prose, so the issue's 'a test covers both cases' criterion has a black-box test with a stubbed gh. Per the issue, the credit checks (author, base branch, edits) stay with resolve-pr.

Not verified

  • siblings-line.test.sh was not executed: this lane's Bash runs only the named wrappers, so the test suite is left to the PR's CI
  • The new siblings-line.sh and siblings-line.test.sh are created without the executable bit (sibling scripts are 100755); the lane has no chmod. They are invoked via bash <path>, but a mode check in CI, if any, may flag them
  • ai-slop:audit fix: detect.sh and digest-guard.sh cannot run in this lane, so the deterministic detector pass was skipped; the rubric read of the changed lines by hand found no tells
  • siblings-line.sh matches a Refs: #N line even inside a fenced block or HTML comment, unlike resolve-pr's visibleLines; resolve-pr then declines such a PR, so the only effect is a named PR that earns no credit
  • build/lint: shellcheck and markdownlint were not run directly (not among this lane's wrappers); check-affected's lint tier covered the changed files where it could

Fix

  • plugins/source-control/skills/pull-request/scripts/siblings-line.sh: new script that prints the Siblings: line for the issues a PR closes, or nothing; exit 2 on a failed gh read
  • plugins/source-control/skills/pull-request/scripts/siblings-line.test.sh: new stubbed-gh tests: one sibling, none, several sorted, non-matching bodies (closing, mid-line, other issue, colon-less, two refs), the newest-10 cap, several closed issues sharing one line, gh failure, --repo, bad arguments
  • plugins/source-control/skills/pull-request/reference/create.md: §2.4.0 adds a 'Siblings of a closing pull request' step after CLOSES_LINE is final; §2.4.1 body composition puts ${SIBLINGS_LINE} directly below ${CLOSES_LINE}, above any Hold: line; the --hold bullet now says the hold sits below the…
  • .changes/source-control/work-resolve-issue-issue-13068-41767948125-1-d1c6f5cb.md: patch changelog fragment (Fixed)

Verification

The runner ran each check from the base copy against c322f9e:

  • scripts/check-changelog-fragments.sh --check: passed
  • scripts/check-changed-skills.sh --merge-base: passed

The run reports:

  • read https: //cli.github.com/manual/gh_pr_list: gh pr list --json lists closingIssuesReferences and body among its fields and supports --search with --state merged
  • read .github/scripts/pr-verify/resolve-pr.mjs siblingNumbers/SIBLINGS_PLAIN/creditedSiblings: the printed Siblings: #a, #b form matches SIBLINGS_PLAIN, and more than SIBLINGS_MAX=10 numbers across the body credits none (hence one line capped at 10)
  • check-changelog-fragments: All 6 changelog fragment(s) under .changes/ are valid
  • check-changed-skills: CHECK-SKILL pull-request PASS, 0 errors, 4 pre-existing warnings (description length, SKILL.md size, ready-for-review.md TOC)
  • check-affected: 13 passed, 6 skipped over 4 changed files
  • cant-fail-scan --file siblings-line.test.sh --check: PASS, no gating findings
  • fresh-context review subagent: 1 medium + 3 low findings; fixed the medium (per-issue cap could exceed pr-verify's 10-total limit: now one line across all issues, newest 10) and two lows (paragraph moved after CLOSES_LINE is final; search-lag noted in create.md); fence/HTML-comment-aware Refs…
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/41767948125

Left out: the items under Not verified.

Related

#13068

Lane-Activity: work-resolve-issue/resolve-issue
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

claude-security-review reviewed c322f9e7dc6c3fbefbae2e25c5a5490e43b953d0: read 4 of 4 changed file(s); 0 finding(s), 0 as inline comments.

Security review: PR #13078 (head c322f9e)

I read every hunk of all 4 changed files. None of them matches a trusted path. I found no security issues.

What changed. A new script, siblings-line.sh, with its stubbed-gh test. It lists merged pull requests whose body has a Refs: #N line for an issue this PR closes and that close no issue, then prints one Siblings: #a, #b line of at most 10 numbers. create.md §2.4.0 and §2.4.1 now put that line in the PR body below the closing line. There is also a changelog fragment.

Checks:

  • Shell or regex injection: none. Each issue argument must match ^[1-9][0-9]{0,8}$ (siblings-line.sh#L56) before it reaches the gh --search string or the jq regex (where it is passed via --arg). --repo reaches gh as a single quoted argv element. The regex is anchored on both ends, so #7 does not match #77, and the tests cover that.
  • Credit trust boundary: unchanged. The script does not check who wrote a sibling PR; it only proposes numbers. pr-verify's creditedSiblings (resolve-pr.mjs#L624-L643) re-reads each named PR from GitHub. It credits one only when the PR is merged into the same base in this repository, closes no issue, was written by a trusted human or the lanes App, and has a body that is unedited or was last edited by a trusted editor. The diff does not touch that file. A PR author could already write a Siblings: line by hand, so automating it admits nothing new.
  • Instruction surface: no rule is deleted or narrowed. The --hold line still goes in $BODY_FILE before the first ## block and before the §2.4.2 gates run. It now sits below any Siblings: line, so the hold still applies before ready --unattended can act.
  • Embedded text in the PR context: none found.
  • Spend: a few extra gh pr list reads per create run, one per closed issue. These only use GitHub API quota.

critical-findings: 0

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

claude-review reviewed c322f9e7dc6c3fbefbae2e25c5a5490e43b953d0: read 4 of 4 changed file(s); 0 finding(s), 0 as inline comments.

Code review: PR #13078, no findings

I read every hunk of all 4 changed files: the changelog fragment, create.md, siblings-line.sh and siblings-line.test.sh.

Closing issue #13068: acceptance criteria

  • Writes a first-column Siblings: line naming a merged Refs: pull request. Met. create.md §2.4.0 runs the new script after ${CLOSES_LINE} is final, and §2.4.1 puts a non-empty ${SIBLINGS_LINE} at the first column directly below it. Test case Siblings: #12974 covers the script.
  • With no such pull request, no Siblings: line is written. Met. When nothing matches, jq produces an empty string, so [[ -n ]] prints nothing and the script exits 0. The [] case and the non-matching-bodies case cover this.
  • A test covers both cases and fails without the change. Met at the script level: siblings-line.test.sh would fail without siblings-line.sh. The body placement in create.md is prose and no test covers it, which is normal for this skill's reference docs. I did not run the test suite (this lane has no shell). The PR says the lane that wrote it didn't run it either, so it depends on CI.

Checked against what pr-verify accepts

  • The printed line Siblings: #a, #b matches SIBLINGS_PLAIN in resolve-pr.mjs.

  • unique | .[-10:] keeps the 10 newest pull requests, which matches SIBLINGS_MAX = 10. pr-verify gives no credit to a body that names more than 10.

  • The script's filter ^Refs:[ \t]*#N[ \t]*\r?$ (with (?m)) matches the same lines as REFS_PLAIN in merge-holds.mjs. It also requires an empty closingIssuesReferences, which matches resolve-pr's "closing no issue" condition.

  • The script can name some pull requests that resolve-pr then gives no credit:

    • a Refs: line inside a fence or HTML comment, which the PR body already admits;
    • a body with two Refs: lines, which refsIssue reads as none.

    resolve-pr declines these on its own checks, so the only cost is a wasted slot in the 10.

Other notes

  • Moving Hold: below an optional Siblings: line breaks no reader I could find. check-ready-holds.sh matches Hold: on any line.
  • Eval 53 (evals.json) still expects the Hold: line "directly below the closing-keyword line". That only stays true while that scenario has no siblings, which is how it is set up now. If a future fixture adds a merged Refs: pull request, the eval's wording would need to change.
  • No plugin manifest changed, so there are no manifest lines. The changelog fragment's bump: patch fits a fix.
  • Usage spend: none beyond normal gh reads at PR-create time (one search per closed issue).
  • The PR context contains no embedded instructions aimed at this lane.

@kyle-sexton
kyle-sexton added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 8a1faca Nov 4, 2026
46 checks passed
@kyle-sexton
kyle-sexton deleted the work-resolve-issue/issue-13068-41767948125-1 branch November 4, 2026 04:42
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.

fix(source-control): write the Siblings line when an issue has merged Refs pull requests

1 participant