Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions docs/ADRs/0062-auto-merge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: "62. Auto-merge"
status: Accepted
Comment on lines +2 to +3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. docs/architecture.md not updated 📜 Skill insight ⚙ Maintainability

This PR adds a new ADR marked Accepted, but there is no corresponding update to
docs/architecture.md to reflect the newly decided behavior and annotate any resolved open
questions. This can leave the architecture overview inconsistent with the accepted decision and
makes it harder to discover the current state of the system.
Agent Prompt
## Issue description
A new ADR (`0062-auto-merge`) is introduced as `Accepted`, but the architecture overview is not updated to reflect/record the decision and to annotate any relevant resolved open questions.

## Issue Context
The compliance rules require that when an ADR is accepted, `docs/architecture.md` is updated in the same PR (and resolved open questions are annotated as resolved rather than left dangling).

## Fix Focus Areas
- docs/ADRs/0062-auto-merge.md[2-3]
- docs/architecture.md[138-200]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

relates_to:
- agent-architecture
- security-threat-model
topics:
- github-apps
- least-privilege
- auto-merge
---

# 62. Auto-merge

Date: 2026-06-30

## Status

Accepted

## Context

Our review bot (`fullsend-ai-review`) can approve PRs, but GitHub only counts
an approval toward branch protection when the reviewer has write access
(`contents: write`) to the repository. The review app intentionally has
`contents: read` — giving it write access would violate the least-privilege
boundary established in [ADR 7](0007-per-role-github-apps.md).

We also need the bot's approval to satisfy CODEOWNERS for dependency files
(`go.mod`, `go.sum`). GitHub App bots cannot be listed as CODEOWNERS entries —
they are not "users" in GitHub's model.

Comment on lines +21 to +32

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Context lacks problem doc links 📜 Skill insight ⚙ Maintainability

The ADR Context describes motivations but does not link to the related problem documents, despite
listing them in relates_to. This makes it harder to trace the decision back to the canonical
problem statements and risks duplicating/fragmenting context over time.
Agent Prompt
## Issue description
The ADR Context should link to the relevant problem docs rather than standing alone.

## Issue Context
The ADR declares `relates_to` entries for `agent-architecture` and `security-threat-model`, but the Context section does not include links to those problem documents.

## Fix Focus Areas
- docs/ADRs/0062-auto-merge.md[4-6]
- docs/ADRs/0062-auto-merge.md[21-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

## Options

### A. Add `contents: write` to the review app

Collapses the permission boundary between review and implementation roles.
Every repo that installs the review app would grant it write access it doesn't
otherwise need.

### B. Create a separate `fullsend-ai-merge` app

A new app with `contents: write` and `pull_requests: write`. Repos opt in to
auto-merge by installing this app instead of (or alongside) the review app.
The trust escalation is explicit and visible in GitHub's UI.

### C. Exempt dependency files via blank-owner CODEOWNERS entries

Use [blank-owner entries](https://github.com/orgs/community/discussions/23064)
to remove the CODEOWNERS requirement for specific files. This is orthogonal to
the app permission question — it addresses the CODEOWNERS gate, not the
approval-counts gate.

## Decision

Use options B and C together:

1. **Create a `fullsend-ai-merge` app** with `contents: write` and
`pull_requests: write`. Its approvals count toward branch protection. Repos
that want bot-driven auto-merge install this app; repos that only want
informational reviews keep `fullsend-ai-review`.

2. **Use blank-owner CODEOWNERS entries** for files that bots should be able to
approve (starting with `go.mod` and `go.sum`). This removes the CODEOWNERS
gate for those files without affecting other paths.
Comment on lines +54 to +65

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Adr makes two decisions 📜 Skill insight ⚙ Maintainability

The ## Decision section makes two distinct decisions (create a separate merge app, and adopt
blank-owner CODEOWNERS entries), which violates the requirement that each ADR records exactly one
decision. This reduces clarity and makes it harder to supersede or revisit each decision
independently.
Agent Prompt
## Issue description
The ADR's Decision section currently records two distinct decisions.

## Issue Context
Compliance requires each ADR to record exactly one decision; multiple decisions should be split so each can be reviewed, accepted, and superseded independently.

## Fix Focus Areas
- docs/ADRs/0062-auto-merge.md[54-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


## Consequences

- The review app stays read-only — no permission creep.
- Auto-merge is an explicit opt-in per repo, visible in the GitHub App installation list.
- Blank-owner CODEOWNERS entries remove code-owner review for the listed files; CI status checks remain the primary safety gate for those paths.
- Adding a new app increases the number of apps to manage and enroll per org.
- The merge app's `contents: write` permission is a higher-value target if compromised — the same mitigations from [ADR 7](0007-per-role-github-apps.md) apply (repo-scoped install, PEM in config repo secrets).
Loading