Files
multica/server
Bohan Jiang a02e58b488 fix(github): only auto-close issue after all linked PRs resolve (#2470)
* fix(github): only auto-close issue when all linked PRs have resolved

Previously, the webhook handler unconditionally moved an issue to `done`
as soon as a single linked PR was merged. If a second PR was also linked
to the same issue and still open / draft, the issue would close before
the work was actually finished.

Add `CountOpenSiblingPullRequestsForIssue` and gate the auto-status
transition on it: a merged PR advances its linked issues only when no
sibling PR linked to the same issue is still in flight. Issues stay put
while siblings are open or draft, and the merge that resolves the last
in-flight PR is the one that closes the issue.

Adds an integration test that opens two PRs against the same issue,
merges the first, asserts the issue stays in_progress, then merges the
second and asserts the issue advances to done.

Co-authored-by: multica-agent <github@multica.ai>

* fix(github): re-evaluate auto-close on closed-without-merge events too

GPT-Boy review on #2470: gating only the `state == "merged"` branch left
one ordering hole. PR-A merges first → issue stays in_progress because
PR-B is open; PR-B later closes WITHOUT merging → no event ever re-runs
the auto-close check, so the issue is stuck in_progress.

Generalise the trigger to every terminal PR event (`merged` or `closed`)
and advance the issue only when:
- the issue is not already terminal (done / cancelled);
- no sibling PR is still in flight (open / draft);
- at least one linked PR — current or sibling — actually merged.

Rule (3) preserves "user closed every PR without merging → leave the
issue alone": if no work was delivered, the user decides what to do.

Replace `CountOpenSiblingPullRequestsForIssue` with
`GetSiblingPullRequestStateCountsForIssue`, which returns both the
in-flight count and the merged count in a single roundtrip.

Adds `TestWebhook_ClosedSiblingAfterMerge` (the regression GPT-Boy
flagged) and `TestWebhook_AllClosedWithoutMerge` (the negative case
guarding rule 3). Refactors the multi-PR webhook helper out of the
existing two-merge test so all three multi-PR scenarios share it.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-05-12 15:39:55 +08:00
..