MF-8: Merge + review flow parity across forges #299

Closed
opened 2026-04-23 23:33:17 +00:00 by code-lead · 0 comments
Collaborator

As a platform engineer, I want squash-merge and review-verdict behaviour to work identically on all three forges (or degrade gracefully when a feature is missing), so that the post-CI routing state machine is forge-agnostic.

Acceptance criteria

Merge

  • ForgePort.mergePullRequest accepts a strategy: "squash" default.
  • Forgejo adapter maps to Do: squash.
  • GitHub adapter maps to merge_method: squash.
  • GitLab adapter maps to squash: true on the MR accept call.
  • Merge failures surface a consistent typed error shape (MergeError.Unmergeable | .Conflict | .CIFail | .AuthLost).

Reviews

  • Review verdicts (APPROVED / REQUEST_CHANGES / COMMENT) map to each forge:
    • Forgejo + GitHub: native review submit.
    • GitLab: approvals + discussions + reactions (per MF-2 mapping).
  • Replace create_pull_review call sites in domain code with forgePort.submitReview. Adapter translates.
  • listReviews returns the merged shape consistently across forges.

Stale-review flag

  • "Reviewer is stale after a new push":
    • Forgejo: sets ForgeReview.stale.
    • GitHub: dismisses reviews when the repo setting is on.
    • GitLab: re-approval required on push, surfaced as stale: true.
  • Port surfaces this uniformly through the existing stale?: boolean field.

Tests

  • webhook-ci.test.ts: CI → reviewer → approval → merge flow passes per-forge using stubbed adapters.
  • Stale-review behaviour covered per adapter.
  • Merge-error mapping covered for each error category.

Out of scope

  • Advanced merge strategies (merge queue, rebase-merge). Squash-only.
  • Required-reviewer enforcement rules — that stays on the forge side.

References

  • Spec: specs/multi-forge.md § MF-8.
  • apps/server/src/http/webhook-ci.ts — CI state machine consuming merge/review.
  • MF-2 § approvals-as-reviews mapping note.

Dependencies

  • Blocks on MF-4 (adapter factory).
  • Port extensions land on the Forgejo adapter first; MF-1 and MF-2 close their halves in their own stories once the port contract is in place.
  • Depends on #295 (MF-4)
As a platform engineer, I want squash-merge and review-verdict behaviour to work identically on all three forges (or degrade gracefully when a feature is missing), so that the post-CI routing state machine is forge-agnostic. ## Acceptance criteria ### Merge - [ ] `ForgePort.mergePullRequest` accepts a `strategy: "squash"` default. - [ ] Forgejo adapter maps to `Do: squash`. - [ ] GitHub adapter maps to `merge_method: squash`. - [ ] GitLab adapter maps to `squash: true` on the MR accept call. - [ ] Merge failures surface a consistent typed error shape (`MergeError.Unmergeable | .Conflict | .CIFail | .AuthLost`). ### Reviews - [ ] Review verdicts (APPROVED / REQUEST_CHANGES / COMMENT) map to each forge: - Forgejo + GitHub: native review submit. - GitLab: approvals + discussions + reactions (per MF-2 mapping). - [ ] Replace `create_pull_review` call sites in domain code with `forgePort.submitReview`. Adapter translates. - [ ] `listReviews` returns the merged shape consistently across forges. ### Stale-review flag - [ ] "Reviewer is stale after a new push": - Forgejo: sets `ForgeReview.stale`. - GitHub: dismisses reviews when the repo setting is on. - GitLab: re-approval required on push, surfaced as `stale: true`. - [ ] Port surfaces this uniformly through the existing `stale?: boolean` field. ### Tests - [ ] `webhook-ci.test.ts`: CI → reviewer → approval → merge flow passes per-forge using stubbed adapters. - [ ] Stale-review behaviour covered per adapter. - [ ] Merge-error mapping covered for each error category. ## Out of scope - Advanced merge strategies (merge queue, rebase-merge). Squash-only. - Required-reviewer enforcement rules — that stays on the forge side. ## References - Spec: [`specs/multi-forge.md`](../src/branch/main/specs/multi-forge.md) § MF-8. - `apps/server/src/http/webhook-ci.ts` — CI state machine consuming merge/review. - MF-2 § approvals-as-reviews mapping note. ## Dependencies - **Blocks on MF-4** (adapter factory). - Port extensions land on the Forgejo adapter first; MF-1 and MF-2 close their halves in their own stories once the port contract is in place. <!-- machine-parseable deps for the deps.ts body fallback; native POST /dependencies is currently returning HTTP 404 on this Forgejo. --> - Depends on #295 (MF-4)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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
charles/claude-hooks#299
No description provided.