DEV Community

Taylor Wang
Taylor Wang

Posted on

Gate OSS Patches With a Four-Check Review Packet

Maintainers merge evidence packets, not clever one-line diffs. A green local test still leaves scope and docs unchecked. This workflow freezes a contribution packet before any pull request.

Cheap model output makes patches easy to draft. It does not make them cheap to review. Agents also invent missing context and then patch the invention. The packet below blocks that habit with four numbered gates.

The example uses a fictional library named linebuf. The library should keep one trailing newline. It currently drops blank lines at end of file. The walkthrough is labeled as an unexecuted template, not a live claim.

What the packet must contain

Every outbound OSS change needs four artifacts on disk. They live beside the branch, not in chat history. Reviewers can clone the branch and replay the same files.

  1. issue.md with the original report text.
  2. repro.md with exact commands and observed output.
  3. failing_test.patch created before production edits.
  4. review.json written after tests turn green.

Skip the packet and the model starts guessing. Guessing is how drive-by PRs waste maintainer time.

Gate 1: lock the reproduction

Do not open an editor on library code yet. Recreate the failure with a test the project already runs. The test file becomes the contract for later review.

git fetch origin
git switch -c issue-884-trailing-newline origin/main
mkdir -p tests/repro
Enter fullscreen mode Exit fullscreen mode

Add a focused test that names the issue and the input. Keep the first commit limited to that file.

# tests/repro/test_issue_884_trailing_newline.py
from linebuf import normalize


def test_issue_884_keeps_single_trailing_newline():
    raw = "alpha\nbeta\n"
    assert normalize(raw).endswith("\n")
    assert not normalize(raw).endswith("\n\n")
Enter fullscreen mode Exit fullscreen mode

Run only that node before touching src/.

pytest tests/repro/test_issue_884_trailing_newline.py -q
# expected: 1 failed
git add tests/repro/test_issue_884_trailing_newline.py
git commit -m "test: lock issue 884 trailing newline repro"
Enter fullscreen mode Exit fullscreen mode

A passing test at this gate means the report is already stale. Stop and re-read the issue. Do not invent a new bug for the model to solve.

Gate 2: lock the file scope

List nouns from the issue. Map each noun to one path. Reject extra files before they enter the index. Models pad diffs with helpers, renames, and drive-by lint.

printf '%s\n' 'normalize' 'trailing newline' 'end of file' > /tmp/issue-nouns.txt
git diff --name-only origin/main...HEAD > /tmp/changed.txt
Enter fullscreen mode Exit fullscreen mode

Keep a hard allowlist for this issue. linebuf only needs the normalizer and the new test.

# /tmp/allowlist.txt
src/linebuf/normalize.py
tests/repro/test_issue_884_trailing_newline.py
Enter fullscreen mode Exit fullscreen mode

A small checker fails the branch when the diff escapes that list.

# tools/scope_lock.py
from pathlib import Path
import sys

allow = set(Path("/tmp/allowlist.txt").read_text().splitlines())
changed = set(Path("/tmp/changed.txt").read_text().splitlines())
extra = sorted(p for p in changed if p and p not in allow)
if extra:
    print("scope lock failed:")
    print("\n".join(extra))
    sys.exit(1)
print("scope lock passed")
Enter fullscreen mode Exit fullscreen mode

Run it after every commit. Scope creep is a review reject, not a style nit.

Gate 3: lock the public contract

Green tests can still ship a silent API break. Gate 3 is a checklist, not a linter plugin. Fill it in review.json by hand first.

{
  "issue": "884",
  "public_signatures_changed": false,
  "changelog_entry": true,
  "issue_linked_in_pr_body": true,
  "test_names_include_issue_id": true,
  "docs_touched": false,
  "notes": "normalize() return type unchanged"
}
Enter fullscreen mode Exit fullscreen mode

Use this reject matrix when a box cannot be honest. The matrix is the original artifact for this account.

Reject reason Signal on the branch Required packet fix
Missing reproduction No failing test commit Add Gate 1 commit first
Scope creep Files outside allowlist Revert extras, rerun scope lock
Silent API change Signature or types shifted Restore signature or version docs
Unlinked issue PR body lacks Fixes # Rewrite the PR template
Hidden behavior change Changelog skipped Add a one-line user note
Model-authored junk Comments, renames, dead helpers Delete and rerun tests

Do not ask a model to tick these boxes from memory. Read git diff origin/main and the test output. Write the JSON only after that read.

Gate 4: second reader, never author

The patch already exists. Tests already pass. A model now reviews the packet against Gates 1-3. It does not propose new files. It does not rewrite the diff.

Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option. Those two facts are the only product claims used here. No model names, quotas, or hardware details are stated.

The second reader can run on that free model path when a paid API is not needed. The same prompt also runs in any local chat window. The workflow does not depend on one host.

Save this prompt as tools/second_reader.md. Treat it as a proposal, not a measured eval.

You are a maintainer, not a patch author.
Read issue.md, repro.md, git.diff, pytest.txt, and review.json.
Reject the packet if any gate fails.
Return only YAML with keys: verdict, failed_gates, maintainer_comment.
verdict must be accept or reject.
Do not suggest extra refactors.
Do not rewrite source.
Quote failing evidence with file paths.
Enter fullscreen mode Exit fullscreen mode

Collect the inputs with a single script. The script writes a folder a human can attach.

# tools/build_packet.py
from pathlib import Path
import subprocess
import sys

root = Path("packet")
root.mkdir(exist_ok=True)

def run(cmd: list[str]) -> str:
    p = subprocess.run(cmd, check=False, text=True, capture_output=True)
    return (p.stdout or "") + (p.stderr or "")

(root / "git.diff").write_text(run(["git", "diff", "origin/main"]))
(root / "pytest.txt").write_text(
    run([sys.executable, "-m", "pytest", "tests/repro", "-q"])
)
for name in ("issue.md", "repro.md", "review.json"):
    src = Path(name)
    if src.exists():
        (root / name).write_text(src.read_text())
print(f"packet ready in {root.resolve()}")
Enter fullscreen mode Exit fullscreen mode

Feed that folder to the second reader. Keep the YAML verdict next to the branch. A reject result is success. It saved a maintainer round trip.

Full loop on the fictional linebuf issue

The numbered path below is the whole tutorial. Each step produces a file the next step consumes.

  1. Copy the issue body into issue.md without edits.
  2. Write repro.md with install commands and one failing run.
  3. Land the failing test as its own commit.
  4. Patch src/linebuf/normalize.py until that test passes.
  5. Run the full suite, not only the new file.
  6. Run tools/scope_lock.py against the allowlist.
  7. Fill review.json from the reject matrix.
  8. Run tools/build_packet.py and store packet/.
  9. Send packet/ through the second-reader prompt.
  10. Open the PR only after verdict: accept.
python tools/scope_lock.py
python tools/build_packet.py
# human reads packet/review.json before any model call
Enter fullscreen mode Exit fullscreen mode

If Gate 4 rejects, fix the packet, not the prompt. Prompt iteration without new evidence creates fluent excuses. The files on disk remain the source of truth.

What this does not prove

The loop does not measure model quality. It does not claim merge-rate gains. It does not replace CI, CODEOWNERS, or human review. Maintainer taste still decides comments, commit splits, and release timing.

Free model access can omit repository context. Large monorepos will overflow a naive packet dump. Secret-bearing diffs must never leave the laptop. Embargoed security issues stay off hosted models.

Projects that forbid AI-assisted contributions should skip Gate 4. The first three gates still apply. They are ordinary engineering, not a product feature.

Who should not use this

Typo-only PRs do not need a four-file packet. First-time docs fixes should stay small. New contributors on tiny READMEs will feel blocked. Maintainers already drowning in process should not add YAML theater.

Teams without tests cannot lock Gate 1. They should add a reproduction script first. A model cannot invent a missing harness and stay honest.

Closing

Ship the packet, then ship the PR. The failing test commit is the real patch. Scope lock, contract JSON, and a second reader only confirm it. Readers can run tools/build_packet.py on any current issue; MonkeyCode free model access and the free server option are optional hosts for Gate 4 when a paid endpoint is not in budget.

Top comments (0)