DEV Community

Alex Zhu
Alex Zhu

Posted on

Name a Merge-Readiness Owner: A One-Page Wiki SOP Before Agent Diffs Hit Main

Last Tuesday your teammate opened a twelve-file pull request that an overnight coding agent had drafted alone. Continuous integration reported green, the description quoted the chat transcript, and nobody on the rotation had actually read the diff. By Wednesday morning a silent retry loop was saturating a shared staging queue, and the original session logs had already scrolled away. You do not need another model comparison; you need a named Merge-Readiness Owner before that pattern repeats.

Why merge readiness is a job, not a feeling

Agent sessions collapse planning, coding, and self-review into one transcript that looks complete from the outside. Green tests often measure the agent's own scaffolding rather than the contract your production callers actually require. A large generated diff can still look correct in pieces while remaining unreviewable, which is how pretend-engineering reaches main. Naming an owner turns that fuzzy discomfort into a stoppable checklist that still requires a human signature.

You already have code owners for directories and on-call owners for incidents, so this role should feel familiar. The Merge-Readiness Owner does not write every patch, and they should not rubber-stamp comments the agent generated. They decide whether a change is small enough, evidenced enough, and reversible enough to enter the shared integration branch. If they are away, a documented backup must hold the same veto, because an unsigned agent pull request is just a draft.

Role, backup, and the handoff window

Write the names in your team wiki before the next shared agent run, not after a bad merge. Keep the rotation weekly so the job does not stick to the person who first complained about unreadable diffs. Treat handoff as a five-minute ritual at the start of the owner window, with the previous owner pasting unfinished evidence packs.

  1. Primary owner: the engineer who may mark merge-readiness for agent-assisted pull requests during this week.
  2. Backup owner: the engineer who inherits the same veto if the primary stays offline more than two working hours.
  3. Producer: whoever launched the agent session, which may be the primary owner or a different teammate.
  4. Integrator: the person who presses merge only after the owner posts a complete evidence pack.

The producer may be the owner, but you should still fill both fields so the audit trail stays readable. When the producer and owner are the same person, the backup must glance at the evidence pack before merge. That extra pair of eyes is the whole point of the ritual, and it should not be treated as optional paperwork.

The one-page wiki SOP you can paste

Copy the block below into your team wiki and replace the placeholders with this week's names. Do not expand the page into a novel, because a wall of text will not stop a Friday merge. Keep the stop conditions boring and numerical so an exhausted backup can apply them after dinner.

# Merge-Readiness SOP (agent-assisted PRs)

## Owners this week
- Primary: @name
- Backup: @name
- Escalation (engineering manager): @name
- Owner window: Monday 10:00 to Friday 16:00 local

## Applies when
- Any pull request where an agent produced more than one source file
- Any pull request whose description is mainly a chat export
- Any change that touches shared CI, migrations, auth, or queue consumers

## Ready-to-merge means all of the following
1. Diff budget: <= 400 changed lines OR an explicit owner waiver in the PR
2. File budget: <= 8 touched production files, excluding generated lockfiles
3. Human review note: a HUMAN_REVIEW section in the PR body, written by a person
4. Repro: one command the backup can run without the original chat
5. Rollback: one revert plan that does not require re-opening the agent
6. Secrets scan: no new .env, token, or host files in the diff
7. Signature: primary or backup comment `READINESS: PASS` on the PR

## Hard stops
- Agent-written tests are the only new tests
- The session cannot be replayed from committed prompts or scripts
- The producer cannot explain the diff in five minutes
- CI was greened by skipping a required check

## Handoff
- Unfinished packs move to the backup with a link and a deadline
- After Friday 16:00, agent-assisted merges wait until the next window
Enter fullscreen mode Exit fullscreen mode

That page is the working contract for the week, and every later command exists only to make it executable. Store a link to the page in the pull request template so producers cannot claim they never saw the budgets. If your template already asks for screenshots, add the readiness marker beside that field instead of creating a second form.

A numbered run for the next agent pull request

Walk this sequence in order, and keep the pull request in draft when any step fails. Green CI does not skip a step, and a complete chat export does not skip a step either. You are measuring whether a human can still own the change after the session disappears.

  1. Freeze the producer session and commit the prompts or command files that actually produced the branch.
  2. Ask the producer for a five-minute walkthrough of the behavioral change, not a tour of the transcript.
  3. Run your usual test target plus one command that exercises the production path the diff claims to fix.
  4. Count changed lines and production files, then compare those counts against the wiki budgets before style talk.
  5. Reject the pack when the only new tests sit beside agent-generated helpers that merely mirror the implementation.
  6. Require a rollback note that names the revert command, the feature flag, or the forward-fix owner.
  7. Scan the diff for secrets, credentials, and machine-specific paths before anyone debates naming or formatting.
  8. Post READINESS: PASS or READINESS: BLOCK with failing step numbers, then stop adding optional commentary.

You should record the step that failed, because a vague cleanup comment returns as another huge agent rewrite. Specific step numbers keep the producer from restarting the whole session as a stalling tactic. The owner may waive the line budget, but the waiver must quote a reason the backup can reread later.

Artifact: a merge-readiness contract and a local checker

Keep a committed YAML contract next to the wiki so the budgets cannot drift inside chat threads. The file below is a starting point you can tighten after two weeks of real pull requests. Tune the numbers using your own history rather than copying another team's thresholds from a talk.

# merge_readiness.yml
version: 1
diff_line_budget: 400
production_file_budget: 8
require_human_review_heading: true
forbid_only_agent_tests: true
required_pr_marker: "READINESS: PASS"
hard_stop_paths:
  - ".env"
  - "token"
  - "credentials"
waiver_label: "readiness-waiver"
Enter fullscreen mode Exit fullscreen mode

The checker below is a local helper, not a security scanner and not a proof of correctness. Run it from the repository root against your merge base so the owner and the producer see the same numbers. Treat binary files as budget exceptions in the waiver, not as silent skips inside the script.

#!/usr/bin/env python3
"""Merge-readiness helper for agent-assisted pull requests.

This script measures reviewability budgets. It does not approve merges.
"""
from __future__ import annotations

import argparse
import subprocess
import sys
from pathlib import Path

try:
    import yaml
except ImportError:
    yaml = None

DEFAULTS = {
    "diff_line_budget": 400,
    "production_file_budget": 8,
    "hard_stop_paths": [".env", "token", "credentials"],
}


def git(*args: str) -> str:
    result = subprocess.run(
        ["git", *args],
        check=True,
        capture_output=True,
        text=True,
    )
    return result.stdout


def load_contract(path: Path) -> dict:
    if not path.exists() or yaml is None:
        return DEFAULTS
    data = yaml.safe_load(path.read_text()) or {}
    merged = dict(DEFAULTS)
    merged.update(data)
    return merged


def changed_files(base: str) -> list[str]:
    output = git("diff", "--name-only", base)
    return [line for line in output.splitlines() if line]


def line_stats(base: str) -> tuple[int, int]:
    output = git("diff", "--numstat", base)
    added = deleted = 0
    for line in output.splitlines():
        parts = line.split("\t")
        if len(parts) < 3 or parts[0] == "-" or parts[1] == "-":
            continue
        added += int(parts[0])
        deleted += int(parts[1])
    return added, deleted


def looks_like_secret(path: str, needles: list[str]) -> bool:
    lowered = path.lower()
    return any(needle.lower() in lowered for needle in needles)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--base", default="origin/main")
    parser.add_argument("--contract", default="merge_readiness.yml")
    args = parser.parse_args()

    contract = load_contract(Path(args.contract))
    files = changed_files(args.base)
    added, deleted = line_stats(args.base)
    changed_lines = added + deleted
    production = [
        path for path in files
        if not path.endswith((".lock", ".sum")) and "/generated/" not in path
    ]

    failures: list[str] = []
    if changed_lines > int(contract["diff_line_budget"]):
        failures.append(
            f"line budget {changed_lines} > {contract['diff_line_budget']}"
        )
    if len(production) > int(contract["production_file_budget"]):
        failures.append(
            f"file budget {len(production)} > {contract['production_file_budget']}"
        )
    for path in files:
        if looks_like_secret(path, contract["hard_stop_paths"]):
            failures.append(f"hard-stop path in diff: {path}")

    print(f"files={len(files)} production={len(production)} lines={changed_lines}")
    if failures:
        print("READINESS: BLOCK")
        for item in failures:
            print(f"- {item}")
        return 1
    print("READINESS: CHECKS_OK (human signature still required)")
    return 0


if __name__ == "__main__":
    sys.exit(main())
Enter fullscreen mode Exit fullscreen mode

Install PyYAML only if you want the YAML contract to load; otherwise the script uses the built-in defaults. Example commands for the owner window are ordinary git and GitHub CLI calls you already trust.

python3 -m pip install --user pyyaml
git fetch origin
python3 merge_readiness_check.py --base origin/main
gh pr comment "$PR" --body "READINESS: BLOCK
- step 4 file budget
- step 6 rollback note missing"
Enter fullscreen mode Exit fullscreen mode

Label the output honestly when you paste it, because a green checker is not a merge approval. CHECKS_OK means the budgets passed, not that the change is correct, and not that the owner has signed. The human comment remains mandatory even when the script exits zero on a clean worktree.

Where a shared free runtime fits

Some teams generate the evidence pack on a laptop that locks, which leaves the backup unable to rerun the checker overnight. If you already use a shared agent workspace for housekeeping, keep the contract and the script in git. Run the same commands in that workspace so the backup can repeat the numbers without the producer's laptop.

Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode's free model access and free server option can host that rerun when you need a room that is not tied to one sleeping laptop. Use it to regenerate the five-minute summary and the rollback note from committed files, then paste results into the pull request. Do not let the shared runtime post READINESS: PASS for you, because that signature is still the owner's job.

Limitations, and who should not use this SOP

This playbook measures reviewability, not product quality, latency, or security beyond a naive path check. The line budget will be wrong for generated protobufs, snapshot tests, and lockfile bumps, so waive those classes in writing. A wiki page cannot replace CODEOWNERS, required reviewers, or a change-management ticket when your organization already mandates them. Treat the checker as a ruler for diff size, not as a secret scanner and not as a proof of behavior.

You should skip this SOP if you are a solo developer merging to a private branch with no shared runtime. You should also skip it when a staffed review rotation already blocks unreadable diffs without extra ceremony. A second owner on top of a working review SLA will mostly add latency and duplicate comments. Regulated environments that need signed artifacts and retained session recordings need a stronger control plane than a wiki. Treat agent-assisted infrastructure changes, including IAM edits and production data backfills, as out of scope until a human writes the plan.

The useful part of the vibe-coding debate is that a green pipeline is being treated as complete engineering evidence. A named Merge-Readiness Owner is a small way to keep the human veto visible when the transcript looks finished. Paste the wiki page, commit the contract, and refuse to merge unsigned agent diffs even when the dashboard is green.

Top comments (0)