DEV Community

Taylor Wang
Taylor Wang

Posted on

Bind OSS Patches to a Replay Command and File Allowlist

Maintainers should reject OSS patches that cannot be replayed locally. A replay command plus a file allowlist bounds later review. Unbounded diffs invite guesses, extra refactors, and silent scope creep.

Unbounded review fails in predictable ways

Most incoming OSS patches still arrive as narrative text. Contributors describe intent inside the pull request body. Reviewers then reconstruct the bug from comments and memory.

That reconstruction stays slow and often remains incomplete. Hidden setup steps vanish between different contributor machines. Green CI can still hide a missing local assertion.

Free models repeat that same failure at higher speed. They load the entire tree without a hard boundary. They invent helpers, renames, and extra error paths.

The reported issue becomes a pretext for a rewrite. Maintainers then review theater instead of a measurable fix. The envelope below removes that theater.

Bound the patch with three artifacts

The review envelope holds three small artifacts only. Each artifact is a file the contributor must ship. Review starts only after those files exist.

  1. A replay command that fails before the fix.
  2. A path allowlist the diff must not escape.
  3. A gate that compares git diff names to that list.

Issue threads remain optional after the gate passes. Screenshots remain optional after the gate passes. The replay command is the actual contract.

Proposed fixture: trailing CSV fields

The next files are a labeled local fixture. They are not a production incident report. A tiny splitter drops trailing empty CSV fields.

Downstream joins then shift every later column. The intended patch is a small semantic change. A full parser rewrite would violate the envelope.

# csv_split.py — proposed fixture, currently broken
def split_row(line: str) -> list[str]:
    parts = line.rstrip("\n").split(",")
    while parts and parts[-1] == "":
        parts.pop()
    return parts
Enter fullscreen mode Exit fullscreen mode
# test_csv_split.py — proposed fixture
from csv_split import split_row


def test_keeps_trailing_empty_field():
    assert split_row("a,b,") == ["a", "b", ""]


def test_keeps_internal_empty_field():
    assert split_row("a,,b") == ["a", "", "b"]
Enter fullscreen mode Exit fullscreen mode

The first test fails on the broken helper. The second test already passes on internal blanks. That split matters during later model review.

A model must not rewrite internals that already work. Extra test churn still counts as scope creep. The prompt later forbids those drive-by edits.

Artifact 1: the replay command

# replay.sh — proposed fixture
#!/usr/bin/env bash
set -euo pipefail
python -m pytest test_csv_split.py -q
Enter fullscreen mode Exit fullscreen mode
chmod +x replay.sh
./replay.sh; echo "exit=$?"
Enter fullscreen mode Exit fullscreen mode

A useful replay exits non-zero on the open bug. A passing replay before the patch proves nothing. Reviewers should stop there and request a failing command.

Keep the replay narrower than the whole suite. Full suites bury the contract inside unrelated noise. One file is enough for the first envelope.

Artifact 2: the path allowlist

# allowlist.txt — proposed fixture
csv_split.py
test_csv_split.py
Enter fullscreen mode Exit fullscreen mode

The allowlist is a deny-by-default review surface. Refactors outside these paths fail the gate. Test-only drive-by edits still need an explicit listed line.

Do not add README.md from habit or politeness. Documentation can land in a follow-up change. The first envelope should stay intentionally tight.

Add a third path only with a written reason. Put that reason in the pull request body. Silence around extra paths is a reject signal.

Artifact 3: the diff gate

# check_envelope.py — proposed fixture
from pathlib import Path
import subprocess
import sys


def git_changed_files() -> list[str]:
    out = subprocess.check_output(
        ["git", "diff", "--name-only", "HEAD"],
        text=True,
    )
    return [line.strip() for line in out.splitlines() if line.strip()]


def load_allowlist(path: str) -> set[str]:
    lines = Path(path).read_text().splitlines()
    return {
        line.strip()
        for line in lines
        if line.strip() and not line.startswith("#")
    }


def main() -> int:
    allowed = load_allowlist("allowlist.txt")
    changed = git_changed_files()
    extra = [path for path in changed if path not in allowed]
    if not Path("replay.sh").exists():
        print("envelope fail: replay.sh is missing")
        return 2
    if not changed:
        print("envelope fail: empty diff")
        return 3
    if extra:
        print("envelope fail: paths outside allowlist")
        for path in extra:
            print(f"  - {path}")
        return 4
    print("envelope ok: diff stays inside allowlist")
    return 0


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

Run the gate before any model sees the patch. The command sequence stays boring on purpose. Boring sequences are easier to replay on a clean clone.

python check_envelope.py
./replay.sh
# apply the production change, then repeat:
python check_envelope.py
./replay.sh
Enter fullscreen mode Exit fullscreen mode

Expected sequence is fail, then pass, with a clean gate. Any other sequence is an automatic reject. Do not negotiate against the table later.

The labeled production fix is a one-expression change. Stop popping trailing empty fields after split. Leave formatting and comments untouched.

# csv_split.py — proposed fix inside the allowlist
def split_row(line: str) -> list[str]:
    return line.rstrip("\n").split(",")
Enter fullscreen mode Exit fullscreen mode

Numbered contributor workflow

Follow these steps in order every time. Do not skip the failing replay. Models enter only after step seven.

  1. Write one failing assertion that names the bug. Keep that test shorter than the patch story. Commit the red test alone when the project allows it.

  2. Add replay.sh so it runs only that assertion file. Avoid a full-suite replay on the first pass. Name the file in the pull request body.

  3. Write allowlist.txt before editing production code. List the production file and the test file. A third path needs a written reason.

  4. Change production code until ./replay.sh finally passes. Stop at the first passing replay. Extra cleanup belongs in a later pull request.

  5. Run python check_envelope.py on the working tree. Reject the branch if extra paths appear. Restore those files instead of expanding the list.

  6. Export a unified diff only after the gate passes. Keep the diff command boring and repeatable. Reviewers should be able to paste it unchanged.

git status --short
git diff --stat
git diff -- csv_split.py test_csv_split.py
Enter fullscreen mode Exit fullscreen mode
  1. Ask a model to review that bounded diff last. Paste replay output, allowlist text, and the diff. Do not paste the rest of the repository.

What the model may do

Give the model a closed instruction set. Treat the next block as a proposed prompt. It is not a measured vendor result.

You are reviewing one bounded OSS patch.
You may comment only on paths in allowlist.txt.
You must treat replay.sh as the acceptance test.
Reject the patch if the diff changes behavior
outside the failing assertion.
Do not suggest renames, formatter sweeps, or new files.
List residual risks in three bullets or fewer.
Enter fullscreen mode Exit fullscreen mode

The prompt restates the envelope in plain words. Models still drift without that restatement. Drop comments that name files outside the list.

Human reviewers apply the same cutoff. Style opinions wait until the table says read. Residual risk bullets stay inside the listed paths.

Decision table

Replay before Replay after Gate Maintainer action
non-zero zero pass Read the bounded diff
zero zero pass Reject; bug was not replayed
non-zero non-zero pass Reject; fix is incomplete
non-zero zero fail Reject; scope left the list
missing any any Reject; envelope is incomplete

The table is the shared review policy. Humans and models both follow it. Arguments about taste wait until a row says read.

Record the accepted row in the merge comment. Future bisects then know the acceptance rule. One line of history is enough.

Where a free model and free server fit

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. This workflow does not depend on named models, published quotas, or special hardware.

The free model is useful after the gate, not before it. Feed it the allowlist, the replay output, and the bounded diff. Ask it for residual risks inside that surface only.

The free server is useful when local replay is awkward. Some contributors cannot install project runtimes on a laptop. Running replay.sh on a spare server keeps the envelope honest.

Clone the branch, run the gate, run the replay, then discard the tree. Do not keep long-lived reviewer state on that machine. The envelope should survive a clean checkout.

The article remains usable without that product. Git, pytest, and a shell already implement the envelope. The model pass is an extra reader, not a merge oracle.

If the envelope already exists, the free model pass is optional. Maintainers can apply the same table by hand. Use the free server only when the laptop cannot replay.

Limitations

This envelope is not a security review. Secret handling, auth flows, and parser attacks need a full-tree read. Do not let an allowlist hide those paths.

This envelope is not an architecture review. Public API changes, data migrations, and feature flags need wider context. Expand the process instead of stretching one allowlist.

This envelope is a poor fit for generated code dumps. Large vendor updates will never stay inside two paths. Use a different contract for those upgrades.

The gate trusts git diff against HEAD only. Untracked files can still leak into a later commit. Run git status beside the gate every time.

The replay command can be cheated on purpose. A contributor might stub the test to pass. Reviewers still read the assertion by hand.

Models will not catch every stub or skipped check. No timing numbers appear here because none were measured. Teams should record their own replay times locally.

Who should skip this approach

Solo prototypes with one author gain little structure. The envelope exists to constrain incoming strangers. Skip it on private spikes and throwaway branches.

Huge first contributions should not fake a tiny allowlist. If the issue needs twenty files, list twenty files. A dishonest two-line allowlist is worse than none.

Projects without tests cannot start at step one. Write the first assertion before inviting any model. The model cannot invent a missing oracle.

Maintainer close-out

After merge, keep fixture-only replay scripts out of immortal policy. Promote replay.sh only when it maps to a stable test path. Delete allowlists that no longer match the tree.

The core rule stays small and local. No replay means no review this round. No allowlist means no model pass this round.

Top comments (0)