issue-300: use Closes keyword in MR description so merges auto-close the issue #302

Merged
yousuf merged 1 commit from feature/issue-300/mr-description-closes-keyword-auto-close into main 2026-09-05 11:30:59 +00:00
Collaborator

What & why

The deterministic MR-description builder opened every MR/PR body with:

Implements [<key>](<url>).

Implements is not a closing keyword on GitLab, GitHub, or Forgejo, so merging a pi-loop MR left the source issue open — operators had to close every issue by hand.

closeIssueAfterAutoMerge (src/orchestrator/services/runPipeline.ts) only fires on the --auto-merge path, so the default Draft-MR flow — the documented human checkpoint — had no issue-closing mechanism at all.

Git-platform issues now get a real closing reference; Jira keeps the descriptive wording because it has no MR-body closing mechanism and its keys are not #-references (Jira is handled by write-back).

Before / after

-Implements [123](https://gitlab.com/acme/widgets/-/issues/123).
+Closes #123 — [123](https://gitlab.com/acme/widgets/-/issues/123).

Jira is unchanged: Implements [ABC-1](…).

Cross-repo issues get the qualified form all three platforms require: Closes acme/tracker#42.

Per-file breakdown

Modified

  • src/mr/helpers/buildMrDescription.ts — new buildIssueReference() helper picks the wording by provider; new optional mrRepo input on BuildMrDescriptionInput so the builder can tell same-repo from cross-repo and emit the qualified reference only when needed.
  • src/mr/services/runMrStage.ts — passes originRepo through as mrRepo.
  • src/mr/helpers/buildMrDescription.test.ts — 7 new cases: closing keyword for each of gitlab/github/forgejo, Jira keeps non-closing wording, issue URL still present, cross-repo qualification, and the two unknown-repo fallbacks.
  • DESIGN.md — §Stage 4 documents the closing-keyword rule and the Jira exception.

Verification

  • npm test — 2083 passed / 144 files
  • npm run lint — clean
  • npm run build — clean

Remaining tsc --noEmit errors are pre-existing in unrelated test files (gitState.test.ts, authenticatedFetch.test.ts, runStage.test.ts) and untouched here.

Note on scope

This fixes the description text. Worth a separate look: closeIssueAfterAutoMerge remains auto-merge-only, so on platforms/repos where closing keywords are disabled the Draft flow still relies on a human.

Closes #300

## What & why The deterministic MR-description builder opened every MR/PR body with: ``` Implements [<key>](<url>). ``` `Implements` is **not a closing keyword** on GitLab, GitHub, or Forgejo, so merging a pi-loop MR left the source issue open — operators had to close every issue by hand. `closeIssueAfterAutoMerge` (`src/orchestrator/services/runPipeline.ts`) only fires on the `--auto-merge` path, so the default Draft-MR flow — the documented human checkpoint — had no issue-closing mechanism at all. Git-platform issues now get a real closing reference; Jira keeps the descriptive wording because it has no MR-body closing mechanism and its keys are not `#`-references (Jira is handled by write-back). ### Before / after ```diff -Implements [123](https://gitlab.com/acme/widgets/-/issues/123). +Closes #123 — [123](https://gitlab.com/acme/widgets/-/issues/123). ``` Jira is unchanged: `Implements [ABC-1](…)`. Cross-repo issues get the qualified form all three platforms require: `Closes acme/tracker#42`. ## Per-file breakdown **Modified** - `src/mr/helpers/buildMrDescription.ts` — new `buildIssueReference()` helper picks the wording by provider; new optional `mrRepo` input on `BuildMrDescriptionInput` so the builder can tell same-repo from cross-repo and emit the qualified reference only when needed. - `src/mr/services/runMrStage.ts` — passes `originRepo` through as `mrRepo`. - `src/mr/helpers/buildMrDescription.test.ts` — 7 new cases: closing keyword for each of gitlab/github/forgejo, Jira keeps non-closing wording, issue URL still present, cross-repo qualification, and the two unknown-repo fallbacks. - `DESIGN.md` — §Stage 4 documents the closing-keyword rule and the Jira exception. ## Verification - `npm test` — 2083 passed / 144 files - `npm run lint` — clean - `npm run build` — clean Remaining `tsc --noEmit` errors are pre-existing in unrelated test files (`gitState.test.ts`, `authenticatedFetch.test.ts`, `runStage.test.ts`) and untouched here. ## Note on scope This fixes the description text. Worth a separate look: `closeIssueAfterAutoMerge` remains auto-merge-only, so on platforms/repos where closing keywords are disabled the Draft flow still relies on a human. Closes #300
The MR-description builder opened every body with `Implements [<key>](<url>)`.
`Implements` is not a closing keyword on GitLab, GitHub, or Forgejo, so merging
a pi-loop MR left the source issue open.

Git-platform issues now get `Closes #<number>`, or the cross-repo
`Closes <owner>/<repo>#<number>` form when the issue lives in another
repository. Jira keeps the descriptive `Implements` wording -- it has no
MR-body closing mechanism and its keys are not `#`-references.
yousuf changed title from WIP: issue-300: use Closes keyword in MR description so merges auto-close the issue to issue-300: use Closes keyword in MR description so merges auto-close the issue 2026-09-03 01:01:09 +00:00
david approved these changes 2026-09-05 11:10:50 +00:00
yousuf merged commit f99c7f6a4f into main 2026-09-05 11:30:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
david/pi-loop!302
No description provided.